From c8dc2e324faf6fe7c8552fba876e3e9c8dcc2454 Mon Sep 17 00:00:00 2001 From: kload Date: Sun, 19 Jul 2015 11:08:18 +0200 Subject: [PATCH 01/86] [enh] Bootstrap the regenconf command --- data/actionsmap/yunohost.yml | 20 + data/templates/amavis/05-domain_id | 19 + data/templates/amavis/05-node_id | 13 + data/templates/amavis/15-content_filter_mode | 23 ++ data/templates/amavis/20-debian_defaults | 216 +++++++++++ data/templates/amavis/50-user.j2 | 30 ++ data/templates/dovecot/dovecot-ipv4.conf.j2 | 71 ++++ data/templates/dovecot/dovecot-ldap.conf | 9 + data/templates/dovecot/dovecot.conf.j2 | 71 ++++ data/templates/dovecot/dovecot.sieve | 4 + data/templates/dovecot/sa-learn-pipe.sh | 9 + data/templates/fail2ban/jail.conf | 344 ++++++++++++++++++ data/templates/fail2ban/yunohost.conf | 24 ++ data/templates/glances/glances.default | 2 + data/templates/metronome/metronome.cfg.lua | 131 +++++++ data/templates/metronome/metronome.init | 101 +++++ data/templates/metronome/metronome.logrotate | 11 + data/templates/metronome/modules/ldap.lib.lua | 270 ++++++++++++++ .../metronome/modules/mod_auth_ldap2.lua | 81 +++++ .../metronome/modules/mod_legacyauth.lua | 87 +++++ .../metronome/modules/mod_storage_ldap.lua | 180 +++++++++ .../templates/metronome/modules/vcard.lib.lua | 162 +++++++++ data/templates/mysql/my.cnf | 89 +++++ data/templates/nginx/server.conf.j2 | 46 +++ data/templates/nginx/ssowat.conf | 3 + data/templates/nginx/yunohost_admin.conf | 35 ++ data/templates/nginx/yunohost_admin.conf.inc | 5 + data/templates/nginx/yunohost_api.conf.inc | 7 + data/templates/nginx/yunohost_local.conf | 1 + data/templates/nginx/yunohost_panel.conf.inc | 2 + data/templates/nslcd/nslcd.conf | 32 ++ data/templates/postfix/header_check | 4 + data/templates/postfix/ldap-accounts.cf | 5 + data/templates/postfix/ldap-aliases.cf | 5 + data/templates/postfix/ldap-domains.cf | 5 + data/templates/postfix/main.cf-ipv4.j2 | 127 +++++++ data/templates/postfix/main.cf.j2 | 126 +++++++ data/templates/postfix/master.cf | 147 ++++++++ data/templates/postfix/postgrey | 12 + data/templates/postfix/sender_canonical | 1 + data/templates/slapd/mailserver.schema | 87 +++++ data/templates/slapd/slapd.conf | 143 ++++++++ data/templates/slapd/slapd.default | 45 +++ data/templates/spamassassin/local.cf | 94 +++++ .../spamassassin/spamassassin.default | 31 ++ data/templates/ssh/sshd_config | 93 +++++ data/templates/ssh/sshd_config-ipv4 | 93 +++++ data/templates/unattended/02periodic | 6 + .../unattended/50unattended-upgrades | 36 ++ lib/yunohost/service.py | 308 +++++++++++++++- 50 files changed, 3463 insertions(+), 3 deletions(-) create mode 100644 data/templates/amavis/05-domain_id create mode 100644 data/templates/amavis/05-node_id create mode 100644 data/templates/amavis/15-content_filter_mode create mode 100644 data/templates/amavis/20-debian_defaults create mode 100644 data/templates/amavis/50-user.j2 create mode 100644 data/templates/dovecot/dovecot-ipv4.conf.j2 create mode 100644 data/templates/dovecot/dovecot-ldap.conf create mode 100644 data/templates/dovecot/dovecot.conf.j2 create mode 100644 data/templates/dovecot/dovecot.sieve create mode 100644 data/templates/dovecot/sa-learn-pipe.sh create mode 100644 data/templates/fail2ban/jail.conf create mode 100644 data/templates/fail2ban/yunohost.conf create mode 100644 data/templates/glances/glances.default create mode 100644 data/templates/metronome/metronome.cfg.lua create mode 100644 data/templates/metronome/metronome.init create mode 100644 data/templates/metronome/metronome.logrotate create mode 100644 data/templates/metronome/modules/ldap.lib.lua create mode 100644 data/templates/metronome/modules/mod_auth_ldap2.lua create mode 100644 data/templates/metronome/modules/mod_legacyauth.lua create mode 100644 data/templates/metronome/modules/mod_storage_ldap.lua create mode 100644 data/templates/metronome/modules/vcard.lib.lua create mode 100644 data/templates/mysql/my.cnf create mode 100644 data/templates/nginx/server.conf.j2 create mode 100644 data/templates/nginx/ssowat.conf create mode 100644 data/templates/nginx/yunohost_admin.conf create mode 100644 data/templates/nginx/yunohost_admin.conf.inc create mode 100644 data/templates/nginx/yunohost_api.conf.inc create mode 100644 data/templates/nginx/yunohost_local.conf create mode 100644 data/templates/nginx/yunohost_panel.conf.inc create mode 100644 data/templates/nslcd/nslcd.conf create mode 100644 data/templates/postfix/header_check create mode 100644 data/templates/postfix/ldap-accounts.cf create mode 100644 data/templates/postfix/ldap-aliases.cf create mode 100644 data/templates/postfix/ldap-domains.cf create mode 100644 data/templates/postfix/main.cf-ipv4.j2 create mode 100644 data/templates/postfix/main.cf.j2 create mode 100644 data/templates/postfix/master.cf create mode 100644 data/templates/postfix/postgrey create mode 100644 data/templates/postfix/sender_canonical create mode 100644 data/templates/slapd/mailserver.schema create mode 100644 data/templates/slapd/slapd.conf create mode 100644 data/templates/slapd/slapd.default create mode 100644 data/templates/spamassassin/local.cf create mode 100644 data/templates/spamassassin/spamassassin.default create mode 100644 data/templates/ssh/sshd_config create mode 100644 data/templates/ssh/sshd_config-ipv4 create mode 100644 data/templates/unattended/02periodic create mode 100644 data/templates/unattended/50unattended-upgrades diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index d05ffeb5..95180f0f 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -869,6 +869,26 @@ service: default: 50 type: int + ### service_regenconf() + regenconf: + action_help: > + Regenerate the configuration file(s) for a service and compare the result + with the existing configuration file. + Prints the differences between files if any. + api: PUT /services/regenconf + arguments: + -n: + full: --name + help: Regenerate configuration for a specfic service + -f: + full: --force + help: Override the current configuration with the newly generated one, even if it has been modified + action: store_true + -k: + full: --keep + help: Save the current configuration to avoid further notifications + action: store_true + ############################# # Firewall # diff --git a/data/templates/amavis/05-domain_id b/data/templates/amavis/05-domain_id new file mode 100644 index 00000000..01a71e4b --- /dev/null +++ b/data/templates/amavis/05-domain_id @@ -0,0 +1,19 @@ +use strict; + +# $mydomain is used just for convenience in the config files and it is not +# used internally by amavisd-new except in the default X_HEADER_LINE (which +# Debian overrides by default anyway). + +#chomp($mydomain = `head -n 1 /etc/mailname`); + +# amavisd-new needs to know which email domains are to be considered local +# to the administrative domain. Only emails to "local" domains are subject +# to certain functionality, such as the addition of spam tags. +# +# Default local domains to $mydomain and all subdomains. Remember to +# override or redefine this if $mydomain is changed later in the config +# sequence. + +@local_domains_acl = ( ".$mydomain" ); + +1; # ensure a defined return diff --git a/data/templates/amavis/05-node_id b/data/templates/amavis/05-node_id new file mode 100644 index 00000000..ee666543 --- /dev/null +++ b/data/templates/amavis/05-node_id @@ -0,0 +1,13 @@ +use strict; + +# $myhostname is used by amavisd-new for node identification, and it is +# important to get it right (e.g. for ESMTP EHLO, loop detection, and so on). + +#chomp($myhostname = `hostname --fqdn`); + +# To manually set $myhostname, edit the following line with the correct Fully +# Qualified Domain Name (FQDN) and remove the # at the beginning of the line. +# +#$myhostname = "mail.example.com"; + +1; # ensure a defined return diff --git a/data/templates/amavis/15-content_filter_mode b/data/templates/amavis/15-content_filter_mode new file mode 100644 index 00000000..825e9e03 --- /dev/null +++ b/data/templates/amavis/15-content_filter_mode @@ -0,0 +1,23 @@ +use strict; + +# You can modify this file to re-enable SPAM checking through spamassassin +# and to re-enable antivirus checking. + +# +# Default antivirus checking mode +# Uncomment the two lines below to enable it back +# + +#@bypass_virus_checks_maps = ( +# \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re); + + +# +# Default SPAM checking mode +# Uncomment the two lines below to enable it back +# + +@bypass_spam_checks_maps = ( + \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re); + +1; # ensure a defined return diff --git a/data/templates/amavis/20-debian_defaults b/data/templates/amavis/20-debian_defaults new file mode 100644 index 00000000..fb8d835d --- /dev/null +++ b/data/templates/amavis/20-debian_defaults @@ -0,0 +1,216 @@ +use strict; + +# ADMINISTRATORS: +# Debian suggests that any changes you need to do that should never +# be "updated" by the Debian package should be made in another file, +# overriding the settings in this file. +# +# The package will *not* overwrite your settings, but by keeping +# them separate, you will make the task of merging changes on these +# configuration files much simpler... + +# see /usr/share/doc/amavisd-new/examples/amavisd.conf-default for +# a list of all variables with their defaults; +# see /usr/share/doc/amavisd-new/examples/amavisd.conf-sample for +# a traditional-style commented file +# [note: the above files were not converted to Debian settings!] +# +# for more details see documentation in /usr/share/doc/amavisd-new +# and at http://www.ijs.si/software/amavisd/amavisd-new-docs.html + +$QUARANTINEDIR = "$MYHOME/virusmails"; +$quarantine_subdir_levels = 1; # enable quarantine dir hashing + +$log_recip_templ = undef; # disable by-recipient level-0 log entries +$DO_SYSLOG = 1; # log via syslogd (preferred) +$syslog_ident = 'amavis'; # syslog ident tag, prepended to all messages +$syslog_facility = 'mail'; +$syslog_priority = 'debug'; # switch to info to drop debug output, etc + +$enable_db = 1; # enable use of BerkeleyDB/libdb (SNMP and nanny) +$enable_global_cache = 1; # enable use of libdb-based cache if $enable_db=1 + +$inet_socket_port = 10024; # default listening socket + +$sa_spam_subject_tag = '***SPAM*** '; +$sa_tag_level_deflt = undef; # add spam info headers if at, or above that level +$sa_tag2_level_deflt = 4.00; # add 'spam detected' headers at that level +$sa_kill_level_deflt = 20.00; # triggers spam evasive actions +$sa_dsn_cutoff_level = 10; # spam level beyond which a DSN is not sent + +$sa_mail_body_size_limit = 200*1024; # don't waste time on SA if mail is larger +$sa_local_tests_only = 0; # only tests which do not require internet access? + +$recipient_delimiter = '+'; +@addr_extension_spam_maps = ('Junk'); + +# Quota limits to avoid bombs (like 42.zip) + +$MAXLEVELS = 14; +$MAXFILES = 1500; +$MIN_EXPANSION_QUOTA = 100*1024; # bytes +$MAX_EXPANSION_QUOTA = 300*1024*1024; # bytes + +# You should: +# Use D_DISCARD to discard data (viruses) +# Use D_BOUNCE to generate local bounces by amavisd-new +# Use D_REJECT to generate local or remote bounces by the calling MTA +# Use D_PASS to deliver the message +# +# Whatever you do, *NEVER* use D_REJECT if you have other MTAs *forwarding* +# mail to your account. Use D_BOUNCE instead, otherwise you are delegating +# the bounce work to your friendly forwarders, which might not like it at all. +# +# On dual-MTA setups, one can often D_REJECT, as this just makes your own +# MTA generate the bounce message. Test it first. +# +# Bouncing viruses is stupid, always discard them after you are sure the AV +# is working correctly. Bouncing real SPAM is also useless, if you cannot +# D_REJECT it (and don't D_REJECT mail coming from your forwarders!). + +$final_virus_destiny = D_DISCARD; # (data not lost, see virus quarantine) +$final_banned_destiny = D_BOUNCE; # D_REJECT when front-end MTA +$final_spam_destiny = D_DISCARD; +$final_bad_header_destiny = D_PASS; # False-positive prone (for spam) + +$enable_dkim_verification = 1; #disabled to prevent warning +$enable_dkim_signing =1; + +$virus_admin = "postmaster\@$mydomain"; # due to D_DISCARD default + +# Set to empty ("") to add no header +$X_HEADER_LINE = "Debian $myproduct_name at $mydomain"; + +# REMAINING IMPORTANT VARIABLES ARE LISTED HERE BECAUSE OF LONGER ASSIGNMENTS + +# +# DO NOT SEND VIRUS NOTIFICATIONS TO OUTSIDE OF YOUR DOMAIN. EVER. +# +# These days, almost all viruses fake the envelope sender and mail headers. +# Therefore, "virus notifications" became nothing but undesired, aggravating +# SPAM. This holds true even inside one's domain. We disable them all by +# default, except for the EICAR test pattern. +# + +@viruses_that_fake_sender_maps = (new_RE( + [qr'\bEICAR\b'i => 0], # av test pattern name + [qr/.*/ => 1], # true for everything else +)); + +@keep_decoded_original_maps = (new_RE( +# qr'^MAIL$', # retain full original message for virus checking (can be slow) + qr'^MAIL-UNDECIPHERABLE$', # recheck full mail if it contains undecipherables + qr'^(ASCII(?! cpio)|text|uuencoded|xxencoded|binhex)'i, +# qr'^Zip archive data', # don't trust Archive::Zip +)); + + +# for $banned_namepath_re, a new-style of banned table, see amavisd.conf-sample + +$banned_filename_re = new_RE( +# qr'^UNDECIPHERABLE$', # is or contains any undecipherable components + + # block certain double extensions anywhere in the base name + qr'\.[^./]*\.(exe|vbs|pif|scr|bat|cmd|com|cpl|dll)\.?$'i, + + qr'\{[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}\}?$'i, # Windows Class ID CLSID, strict + + qr'^application/x-msdownload$'i, # block these MIME types + qr'^application/x-msdos-program$'i, + qr'^application/hta$'i, + +# qr'^application/x-msmetafile$'i, # Windows Metafile MIME type +# qr'^\.wmf$', # Windows Metafile file(1) type + +# qr'^message/partial$'i, qr'^message/external-body$'i, # rfc2046 MIME types + +# [ qr'^\.(Z|gz|bz2)$' => 0 ], # allow any in Unix-compressed +# [ qr'^\.(rpm|cpio|tar)$' => 0 ], # allow any in Unix-type archives +# [ qr'^\.(zip|rar|arc|arj|zoo)$'=> 0 ], # allow any within such archives +# [ qr'^application/x-zip-compressed$'i => 0], # allow any within such archives + + qr'.\.(exe|vbs|pif|scr|bat|cmd|com|cpl)$'i, # banned extension - basic +# qr'.\.(ade|adp|app|bas|bat|chm|cmd|com|cpl|crt|emf|exe|fxp|grp|hlp|hta| +# inf|ins|isp|js|jse|lnk|mda|mdb|mde|mdw|mdt|mdz|msc|msi|msp|mst| +# ops|pcd|pif|prg|reg|scr|sct|shb|shs|vb|vbe|vbs| +# wmf|wsc|wsf|wsh)$'ix, # banned ext - long + +# qr'.\.(mim|b64|bhx|hqx|xxe|uu|uue)$'i, # banned extension - WinZip vulnerab. + + qr'^\.(exe-ms)$', # banned file(1) types +# qr'^\.(exe|lha|tnef|cab|dll)$', # banned file(1) types +); +# See http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262631 +# and http://www.cknow.com/vtutor/vtextensions.htm + + +# ENVELOPE SENDER SOFT-WHITELISTING / SOFT-BLACKLISTING + +@score_sender_maps = ({ # a by-recipient hash lookup table, + # results from all matching recipient tables are summed + +# ## per-recipient personal tables (NOTE: positive: black, negative: white) +# 'user1@example.com' => [{'bla-mobile.press@example.com' => 10.0}], +# 'user3@example.com' => [{'.ebay.com' => -3.0}], +# 'user4@example.com' => [{'cleargreen@cleargreen.com' => -7.0, +# '.cleargreen.com' => -5.0}], + + ## site-wide opinions about senders (the '.' matches any recipient) + '.' => [ # the _first_ matching sender determines the score boost + + new_RE( # regexp-type lookup table, just happens to be all soft-blacklist + [qr'^(bulkmail|offers|cheapbenefits|earnmoney|foryou)@'i => 5.0], + [qr'^(greatcasino|investments|lose_weight_today|market\.alert)@'i=> 5.0], + [qr'^(money2you|MyGreenCard|new\.tld\.registry|opt-out|opt-in)@'i=> 5.0], + [qr'^(optin|saveonlsmoking2002k|specialoffer|specialoffers)@'i => 5.0], + [qr'^(stockalert|stopsnoring|wantsome|workathome|yesitsfree)@'i => 5.0], + [qr'^(your_friend|greatoffers)@'i => 5.0], + [qr'^(inkjetplanet|marketopt|MakeMoney)\d*@'i => 5.0], + ), + +# read_hash("/var/amavis/sender_scores_sitewide"), + +# This are some examples for whitelists, since envelope senders can be forged +# they are not enabled by default. + { # a hash-type lookup table (associative array) + #'nobody@cert.org' => -3.0, + #'cert-advisory@us-cert.gov' => -3.0, + #'owner-alert@iss.net' => -3.0, + #'slashdot@slashdot.org' => -3.0, + #'securityfocus.com' => -3.0, + #'ntbugtraq@listserv.ntbugtraq.com' => -3.0, + #'security-alerts@linuxsecurity.com' => -3.0, + #'mailman-announce-admin@python.org' => -3.0, + #'amavis-user-admin@lists.sourceforge.net'=> -3.0, + #'amavis-user-bounces@lists.sourceforge.net' => -3.0, + #'spamassassin.apache.org' => -3.0, + #'notification-return@lists.sophos.com' => -3.0, + #'owner-postfix-users@postfix.org' => -3.0, + #'owner-postfix-announce@postfix.org' => -3.0, + #'owner-sendmail-announce@lists.sendmail.org' => -3.0, + #'sendmail-announce-request@lists.sendmail.org' => -3.0, + #'donotreply@sendmail.org' => -3.0, + #'ca+envelope@sendmail.org' => -3.0, + #'noreply@freshmeat.net' => -3.0, + #'owner-technews@postel.acm.org' => -3.0, + #'ietf-123-owner@loki.ietf.org' => -3.0, + #'cvs-commits-list-admin@gnome.org' => -3.0, + #'rt-users-admin@lists.fsck.com' => -3.0, + #'clp-request@comp.nus.edu.sg' => -3.0, + #'surveys-errors@lists.nua.ie' => -3.0, + #'emailnews@genomeweb.com' => -5.0, + #'yahoo-dev-null@yahoo-inc.com' => -3.0, + #'returns.groups.yahoo.com' => -3.0, + #'clusternews@linuxnetworx.com' => -3.0, + #lc('lvs-users-admin@LinuxVirtualServer.org') => -3.0, + #lc('owner-textbreakingnews@CNNIMAIL12.CNN.COM') => -5.0, + + # soft-blacklisting (positive score) + #'sender@example.net' => 3.0, + #'.example.net' => 1.0, + + }, + ], # end of site-wide tables +}); + +1; # ensure a defined return diff --git a/data/templates/amavis/50-user.j2 b/data/templates/amavis/50-user.j2 new file mode 100644 index 00000000..129da4f2 --- /dev/null +++ b/data/templates/amavis/50-user.j2 @@ -0,0 +1,30 @@ +use strict; + +# +# Place your configuration directives here. They will override those in +# earlier files. +# +# See /usr/share/doc/amavisd-new/ for documentation and examples of +# the directives you can use in this file +# + +$myhostname = "{{ domain }}"; + +$mydomain = "{{ domain }}"; + +# Enable LDAP support +$enable_ldap = 1; + +# Default LDAP settings +$default_ldap = { + hostname => "127.0.0.1", + tls => 0, + version => 3, + base => "dc=yunohost,dc=org", + scope => "sub", + query_filter => "(&(objectClass=inetOrgPerson)(mail=%m))", +}; + + +#------------ Do not modify anything below this line ------------- +1; # ensure a defined return diff --git a/data/templates/dovecot/dovecot-ipv4.conf.j2 b/data/templates/dovecot/dovecot-ipv4.conf.j2 new file mode 100644 index 00000000..044f0b90 --- /dev/null +++ b/data/templates/dovecot/dovecot-ipv4.conf.j2 @@ -0,0 +1,71 @@ +# 2.1.7: /etc/dovecot/dovecot.conf +# OS: Linux 3.2.0-3-686-pae i686 Debian wheezy/sid ext4 +listen = * +auth_mechanisms = plain login +login_greeting = Dovecot ready!! +mail_gid = 8 +mail_home = /var/mail/%n +mail_location = maildir:/var/mail/%n +mail_uid = 500 +passdb { + args = /etc/dovecot/dovecot-ldap.conf + driver = ldap +} +protocols = imap sieve +service auth { + unix_listener /var/spool/postfix/private/auth { + group = postfix + mode = 0660 + user = postfix + } + unix_listener auth-master { + group = mail + mode = 0660 + user = vmail + } +} + +protocol sieve { +} + +ssl_ca = > /tmp/sa-learn-pipe.log ; +#echo $* > /tmp/sendmail-parms.txt ; +cat<&0 >> /tmp/sendmail-msg-$$.txt ; +/usr/bin/sa-learn $* /tmp/sendmail-msg-$$.txt ; +rm -f /tmp/sendmail-msg-$$.txt ; +echo "$$-end" >> /tmp/sa-learn-pipe.log ; +exit 0; diff --git a/data/templates/fail2ban/jail.conf b/data/templates/fail2ban/jail.conf new file mode 100644 index 00000000..c1cde026 --- /dev/null +++ b/data/templates/fail2ban/jail.conf @@ -0,0 +1,344 @@ +# Fail2Ban configuration file. +# +# This file was composed for Debian systems from the original one +# provided now under /usr/share/doc/fail2ban/examples/jail.conf +# for additional examples. +# +# To avoid merges during upgrades DO NOT MODIFY THIS FILE +# and rather provide your changes in /etc/fail2ban/jail.local +# +# Author: Yaroslav O. Halchenko +# +# $Revision$ +# + +# The DEFAULT allows a global definition of the options. They can be overridden +# in each jail afterwards. + +[DEFAULT] + +# "ignoreip" can be an IP address, a CIDR mask or a DNS host +ignoreip = 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 +bantime = 600 +maxretry = 3 + +# "backend" specifies the backend used to get files modification. Available +# options are "gamin", "polling" and "auto". +# yoh: For some reason Debian shipped python-gamin didn't work as expected +# This issue left ToDo, so polling is default backend for now +backend = auto + +# +# Destination email address used solely for the interpolations in +# jail.{conf,local} configuration files. +destemail = root@localhost + +# +# ACTIONS +# + +# Default banning action (e.g. iptables, iptables-new, +# iptables-multiport, shorewall, etc) It is used to define +# action_* variables. Can be overridden globally or per +# section within jail.local file +banaction = iptables-multiport + +# email action. Since 0.8.1 upstream fail2ban uses sendmail +# MTA for the mailing. Change mta configuration parameter to mail +# if you want to revert to conventional 'mail'. +mta = sendmail + +# Default protocol +protocol = tcp + +# Specify chain where jumps would need to be added in iptables-* actions +chain = INPUT + +# +# Action shortcuts. To be used to define action parameter + +# The simplest action to take: ban only +action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + +# ban & send an e-mail with whois report to the destemail. +action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] + +# ban & send an e-mail with whois report and relevant log lines +# to the destemail. +action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"] + +# Choose default action. To change, just override value of 'action' with the +# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local +# globally (section [DEFAULT]) or per specific section +action = %(action_)s + +# +# JAILS +# + +# Next jails corresponds to the standard configuration in Fail2ban 0.6 which +# was shipped in Debian. Enable any defined here jail by including +# +# [SECTION_NAME] +# enabled = true + +# +# in /etc/fail2ban/jail.local. +# +# Optionally you may override any other parameter (e.g. banaction, +# action, port, logpath, etc) in that section within jail.local + +[ssh] + +enabled = true +port = ssh +filter = sshd +logpath = /var/log/auth.log +maxretry = 6 + +[dropbear] + +enabled = false +port = ssh +filter = sshd +logpath = /var/log/dropbear +maxretry = 6 + +# Generic filter for pam. Has to be used with action which bans all ports +# such as iptables-allports, shorewall +[pam-generic] + +enabled = false +# pam-generic filter can be customized to monitor specific subset of 'tty's +filter = pam-generic +# port actually must be irrelevant but lets leave it all for some possible uses +port = all +banaction = iptables-allports +port = anyport +logpath = /var/log/auth.log +maxretry = 6 + +[xinetd-fail] + +enabled = false +filter = xinetd-fail +port = all +banaction = iptables-multiport-log +logpath = /var/log/daemon.log +maxretry = 2 + + +[ssh-ddos] + +enabled = false +port = ssh +filter = sshd-ddos +logpath = /var/log/auth.log +maxretry = 6 + +# +# HTTP servers +# + +[apache] + +enabled = false +port = http,https +filter = apache-auth +logpath = /var/log/apache*/*error.log +maxretry = 6 + +# default action is now multiport, so apache-multiport jail was left +# for compatibility with previous (<0.7.6-2) releases +[apache-multiport] + +enabled = false +port = http,https +filter = apache-auth +logpath = /var/log/apache*/*error.log +maxretry = 6 + +[apache-noscript] + +enabled = false +port = http,https +filter = apache-noscript +logpath = /var/log/apache*/*error.log +maxretry = 6 + +[apache-overflows] + +enabled = false +port = http,https +filter = apache-overflows +logpath = /var/log/apache*/*error.log +maxretry = 2 + +# +# FTP servers +# + +[vsftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = vsftpd +logpath = /var/log/vsftpd.log +# or overwrite it in jails.local to be +# logpath = /var/log/auth.log +# if you want to rely on PAM failed login attempts +# vsftpd's failregex should match both of those formats +maxretry = 6 + + +[proftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = proftpd +logpath = /var/log/proftpd/proftpd.log +maxretry = 6 + + +[pure-ftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = pure-ftpd +logpath = /var/log/auth.log +maxretry = 6 + + +[wuftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = wuftpd +logpath = /var/log/auth.log +maxretry = 6 + + +# +# Mail servers +# + +[postfix] + +enabled = true +port = smtp,ssmtp +filter = postfix +logpath = /var/log/mail.log + +enabled = false +port = smtp,ssmtp +filter = couriersmtp +logpath = /var/log/mail.log + + +# +# Mail servers authenticators: might be used for smtp,ftp,imap servers, so +# all relevant ports get banned +# + +[courierauth] + +enabled = false +port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s +filter = courierlogin +logpath = /var/log/mail.log + + +[sasl] + +enabled = true +port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s +filter = sasl +# You might consider monitoring /var/log/mail.warn instead if you are +# running postfix since it would provide the same log lines at the +# "warn" level but overall at the smaller filesize. +logpath = /var/log/mail.log + +[dovecot] + +enabled = true +port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s +filter = dovecot +logpath = /var/log/mail.log + + +# DNS Servers + + +# These jails block attacks against named (bind9). By default, logging is off +# with bind9 installation. You will need something like this: +# +# logging { +# channel security_file { +# file "/var/log/named/security.log" versions 3 size 30m; +# severity dynamic; +# print-time yes; +# }; +# category security { +# security_file; +# }; +# }; +# +# in your named.conf to provide proper logging + +# !!! WARNING !!! +# Since UDP is connection-less protocol, spoofing of IP and imitation +# of illegal actions is way too simple. Thus enabling of this filter +# might provide an easy way for implementing a DoS against a chosen +# victim. See +# http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html +# Please DO NOT USE this jail unless you know what you are doing. +#[named-refused-udp] +# +#enabled = false +#port = domain,953 +#protocol = udp +#filter = named-refused +#logpath = /var/log/named/security.log + +[named-refused-tcp] + +enabled = false +port = domain,953 +protocol = tcp +filter = named-refused +logpath = /var/log/named/security.log + +[nginx] + +enabled = true +port = http,https +filter = apache-auth +logpath = /var/log/nginx*/*error.log +maxretry = 6 + +[nginx-noscript] + +enabled = false +port = http,https +filter = apache-noscript +logpath = /var/log/nginx*/*error.log +maxretry = 6 + +[nginx-overflows] + +enabled = false +port = http,https +filter = apache-overflows +logpath = /var/log/nginx*/*error.log +maxretry = 4 + +[yunohost] + +enabled = true +port = http,https +protocol = tcp +filter = yunohost +logpath = /var/log/nginx/*.log +maxretry = 6 diff --git a/data/templates/fail2ban/yunohost.conf b/data/templates/fail2ban/yunohost.conf new file mode 100644 index 00000000..54d4a779 --- /dev/null +++ b/data/templates/fail2ban/yunohost.conf @@ -0,0 +1,24 @@ +# Fail2Ban configuration file +# +# Author: Adrien Beudin +# +# $Revision: 2 $ +# + +[Definition] + +# Option: failregex +# Notes.: regex to match the password failure messages in the logfile. The +# host must be matched by a group named "host". The tag "" can +# be used for standard IP/hostname matching and is only an alias for +# (?:::f{4,6}:)?(?P[\w\-.^_]+) +# Values: TEXT +# +failregex = access.lua:[1-9]+: authenticate\(\): Connection failed for: .*, client: + ^ -.*\"POST /yunohost/api/login HTTP/1.1\" 401 22 + +# Option: ignoreregex +# Notes.: regex to ignore. If this regex matches, the line is ignored. +# Values: TEXT +# +ignoreregex = diff --git a/data/templates/glances/glances.default b/data/templates/glances/glances.default new file mode 100644 index 00000000..90c29eb7 --- /dev/null +++ b/data/templates/glances/glances.default @@ -0,0 +1,2 @@ +DAEMON_ARGS="-B 127.0.0.1" +RUN="yes" diff --git a/data/templates/metronome/metronome.cfg.lua b/data/templates/metronome/metronome.cfg.lua new file mode 100644 index 00000000..240dc4e2 --- /dev/null +++ b/data/templates/metronome/metronome.cfg.lua @@ -0,0 +1,131 @@ +-- ** Metronome's config file example ** +-- +-- The format is exactly equal to Prosody's: +-- +-- Lists are written { "like", "this", "one" } +-- Lists can also be of { 1, 2, 3 } numbers, etc. +-- Either commas, or semi-colons; may be used as seperators. +-- +-- A table is a list of values, except each value has a name. An +-- example would be: +-- +-- ssl = { key = "keyfile.key", certificate = "certificate.crt" } +-- +-- Tip: You can check that the syntax of this file is correct when you have finished +-- by running: luac -p metronome.cfg.lua +-- If there are any errors, it will let you know what and where they are, otherwise it +-- will keep quiet. + +-- Global settings go in this section + +-- This is the list of modules Metronome will load on startup. +-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too. + +pidfile = "/var/run/metronome/metronome.pid" + +log = { + info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging + error = "/var/log/metronome/metronome.err"; + "*syslog"; +} + +modules_enabled = { + + -- Generally required + "roster"; -- Allow users to have a roster. Recommended ;) + "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. + "tls"; -- Add support for secure TLS on c2s/s2s connections + "dialback"; -- s2s dialback support + "disco"; -- Service discovery + + -- Not essential, but recommended + "private"; -- Private XML storage (for room bookmarks, etc.) + "vcard"; -- Allow users to set vCards + "privacy"; -- Support privacy lists + --"compression"; -- Stream compression (Debian: requires lua-zlib module to work) + + -- Nice to have + "legacyauth"; -- Legacy authentication. Only used by some old clients and bots. + "version"; -- Replies to server version requests + "uptime"; -- Report how long server has been running + "time"; -- Let others know the time here on this server + "ping"; -- Replies to XMPP pings with pongs + "pep"; -- Enables users to publish their mood, activity, playing music and more + "register"; -- Allow users to register on this server using a client and change passwords + "adhoc"; -- Support for "ad-hoc commands" that can be executed with an XMPP client + + -- Admin interfaces + "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands + "admin_telnet"; -- Opens telnet console interface on localhost port 5582 + + -- Other specific functionality + "bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" + --"httpserver"; -- Serve static files from a directory over HTTP + --"groups"; -- Shared roster support + --"announce"; -- Send announcement to all online users + --"welcome"; -- Welcome users who register accounts + --"watchregistrations"; -- Alert admins of registrations + --"motd"; -- Send a message to users when they log in + "mam"; -- Nice archive management + -- Debian: do not remove this module, or you lose syslog + -- support + "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. +}; + +-- Discovery items +disco_items = { + { "muc.yunohost.org" }, + { "vjud.yunohost.org" }, + { "pubsub.yunohost.org" } +}; + +use_ipv6 = true +c2s_require_encryption = false +s2s_secure = true + +-- HTTP ports +http_ports = { 5290 } +https_ports = { 5291 } + +-- BOSH configuration (mod_bosh) +bosh_max_inactivity = 30 +consider_bosh_secure = true +cross_domain_bosh = true + +anonymous_login = false +allow_registration = false + +storage = "ldap" + +Component "localhost" "http" + modules_enabled = { "bosh" } + +Component "muc.yunohost.org" "muc" + name = "YunoHost Chatrooms" + + modules_enabled = { + "muc_limits"; + "muc_log"; + "muc_log_http"; + } + + muc_event_rate = 0.5 + muc_burst_factor = 10 + + muc_log_http = { + http_port = 5290; + show_join = true; + show_status = false; + theme = "metronome"; + } + +Component "pubsub.yunohost.org" "pubsub" + name = "YunoHost Publish/Subscribe" + unrestricted_node_creation = true + +Component "vjud.yunohost.org" "vjud" + ud_disco_name = "Jappix User Directory" + +Include "conf.d/*.cfg.lua" + + diff --git a/data/templates/metronome/metronome.init b/data/templates/metronome/metronome.init new file mode 100644 index 00000000..62c04846 --- /dev/null +++ b/data/templates/metronome/metronome.init @@ -0,0 +1,101 @@ +#! /bin/sh + +### BEGIN INIT INFO +# Provides: metronome +# Required-Start: $network $local_fs $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Metronome XMPP Server +### END INIT INFO + +set -e + +# /etc/init.d/metronome: start and stop Metronome XMPP server + +DAEMON=/usr/bin/metronome +PIDPATH=/var/run/metronome +PIDFILE="$PIDPATH"/metronome.pid +RUNTIME=/usr/bin/lua5.1 + +NICE= +MAXFDS= +CPUSCHED= +IOSCHED= + +test -x "$DAEMON" || exit 0 + +if [ -f /etc/default/metronome ] ; then + . /etc/default/metronome +fi + +if [ ! -d "$PIDPATH" ]; then + mkdir "$PIDPATH"; + chown metronome:adm "$PIDPATH"; +fi + +# Check that user 'metronome' exists +check_user() { + if ! getent passwd metronome >/dev/null; then + exit 1; + fi +} + +start_opts() { + test -z "$NICE" || echo -n " --nicelevel $NICE" + test -z "$CPUSCHED" || echo -n " --procsched $CPUSCHED" + test -z "$IOSCHED" || echo -n " --iosched $IOSCHED" +} + +. /lib/lsb/init-functions + +test -z "$MAXFDS" || ulimit -n "$MAXFDS" + +case "$1" in + start) + check_user + log_daemon_msg "Starting Metronome XMPP Server" "metronome" + + if start-stop-daemon --start --quiet --oknodo --pidfile "$PIDFILE" --chuid metronome $(start_opts) --exec "$RUNTIME" -- "$DAEMON"; then + log_end_msg 0 + else + log_end_msg 1 + fi + ;; + stop) + log_daemon_msg "Stopping Metronome XMPP Server" "metronome" + if start-stop-daemon --stop --retry 30 --quiet --oknodo --pidfile "$PIDFILE"; then + log_end_msg 0 + else + log_end_msg 1 + fi + ;; + force-reload|restart) + log_daemon_msg "Restarting Metronome XMPP Server" "metronome" + + start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile "$PIDFILE" + + check_user log_end_msg + + if start-stop-daemon --start --quiet --oknodo --pidfile "$PIDFILE" --chuid metronome $(start_opts) --exec "$RUNTIME" -- "$DAEMON"; then + log_end_msg 0 + else + log_end_msg 1 + fi + ;; + reload) + log_daemon_msg "Reloading Metronome XMPP Server" "metronome" + + if start-stop-daemon --stop --quiet --pidfile "$PIDFILE" --signal 1; then + log_end_msg 0 + else + log_end_msg 1 + fi + ;; + *) + log_action_msg "Usage: /etc/init.d/metronome {start|stop|restart|reload}" + exit 1 +esac + +exit 0 + diff --git a/data/templates/metronome/metronome.logrotate b/data/templates/metronome/metronome.logrotate new file mode 100644 index 00000000..aa145429 --- /dev/null +++ b/data/templates/metronome/metronome.logrotate @@ -0,0 +1,11 @@ +/var/log/metronome/metronome.log /var/log/metronome/metronome.err { + daily + rotate 14 + compress + create 640 metronome adm + postrotate + /etc/init.d/metronome reload > /dev/null + endscript + sharedscripts + missingok +} diff --git a/data/templates/metronome/modules/ldap.lib.lua b/data/templates/metronome/modules/ldap.lib.lua new file mode 100644 index 00000000..6774e735 --- /dev/null +++ b/data/templates/metronome/modules/ldap.lib.lua @@ -0,0 +1,270 @@ +-- vim:sts=4 sw=4 + +-- Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- Copyright (C) 2012 Rob Hoelz +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + +local ldap; +local connection; +local params = module:get_option("ldap"); +local format = string.format; +local tconcat = table.concat; + +local _M = {}; + +local config_params = { + hostname = 'string', + user = { + basedn = 'string', + namefield = 'string', + filter = 'string', + usernamefield = 'string', + }, + groups = { + basedn = 'string', + namefield = 'string', + memberfield = 'string', + + _member = { + name = 'string', + admin = 'boolean?', + }, + }, + admin = { + _optional = true, + basedn = 'string', + namefield = 'string', + filter = 'string', + } +} + +local function run_validation(params, config, prefix) + prefix = prefix or ''; + + -- verify that every required member of config is present in params + for k, v in pairs(config) do + if type(k) == 'string' and k:sub(1, 1) ~= '_' then + local is_optional; + if type(v) == 'table' then + is_optional = v._optional; + else + is_optional = v:sub(-1) == '?'; + end + + if not is_optional and params[k] == nil then + return nil, prefix .. k .. ' is required'; + end + end + end + + for k, v in pairs(params) do + local expected_type = config[k]; + + local ok, err = true; + + if type(k) == 'string' then + -- verify that this key is present in config + if k:sub(1, 1) == '_' or expected_type == nil then + return nil, 'invalid parameter ' .. prefix .. k; + end + + -- type validation + if type(expected_type) == 'string' then + if expected_type:sub(-1) == '?' then + expected_type = expected_type:sub(1, -2); + end + + if type(v) ~= expected_type then + return nil, 'invalid type for parameter ' .. prefix .. k; + end + else -- it's a table (or had better be) + if type(v) ~= 'table' then + return nil, 'invalid type for parameter ' .. prefix .. k; + end + + -- recurse into child + ok, err = run_validation(v, expected_type, prefix .. k .. '.'); + end + else -- it's an integer (or had better be) + if not config._member then + return nil, 'invalid parameter ' .. prefix .. tostring(k); + end + ok, err = run_validation(v, config._member, prefix .. tostring(k) .. '.'); + end + + if not ok then + return ok, err; + end + end + + return true; +end + +local function validate_config() + if true then + return true; -- XXX for now + end + + -- this is almost too clever (I mean that in a bad + -- maintainability sort of way) + -- + -- basically this allows a free pass for a key in group members + -- equal to params.groups.namefield + setmetatable(config_params.groups._member, { + __index = function(_, k) + if k == params.groups.namefield then + return 'string'; + end + end + }); + + local ok, err = run_validation(params, config_params); + + setmetatable(config_params.groups._member, nil); + + if ok then + -- a little extra validation that doesn't fit into + -- my recursive checker + local group_namefield = params.groups.namefield; + for i, group in ipairs(params.groups) do + if not group[group_namefield] then + return nil, format('groups.%d.%s is required', i, group_namefield); + end + end + + -- fill in params.admin if you can + if not params.admin and params.groups then + local admingroup; + + for _, groupconfig in ipairs(params.groups) do + if groupconfig.admin then + admingroup = groupconfig; + break; + end + end + + if admingroup then + params.admin = { + basedn = params.groups.basedn, + namefield = params.groups.memberfield, + filter = group_namefield .. '=' .. admingroup[group_namefield], + }; + end + end + end + + return ok, err; +end + +-- what to do if connection isn't available? +local function connect() + return ldap.open_simple(params.hostname, params.bind_dn, params.bind_password, params.use_tls); +end + +-- this is abstracted so we can maintain persistent connections at a later time +function _M.getconnection() + return connect(); +end + +function _M.getparams() + return params; +end + +-- XXX consider renaming this...it doesn't bind the current connection +function _M.bind(username, password) + local conn = _M.getconnection(); + local filter = format('%s=%s', params.user.usernamefield, username); + if params.user.usernamefield == 'mail' then + filter = format('mail=%s@*', username); + end + + if filter then + filter = _M.filter.combine_and(filter, params.user.filter); + end + + local who = _M.singlematch { + attrs = params.user.usernamefield, + base = params.user.basedn, + filter = filter, + }; + + if who then + who = who.dn; + module:log('debug', '_M.bind - who: %s', who); + else + module:log('debug', '_M.bind - no DN found for username = %s', username); + return nil, format('no DN found for username = %s', username); + end + + local conn, err = ldap.open_simple(params.hostname, who, password, params.use_tls); + + if conn then + conn:close(); + return true; + end + + return conn, err; +end + +function _M.singlematch(query) + local ld = _M.getconnection(); + + query.sizelimit = 1; + query.scope = 'subtree'; + + for dn, attribs in ld:search(query) do + attribs.dn = dn; + return attribs; + end +end + +_M.filter = {}; + +function _M.filter.combine_and(...) + local parts = { '(&' }; + + local arg = { ... }; + + for _, filter in ipairs(arg) do + if filter:sub(1, 1) ~= '(' and filter:sub(-1) ~= ')' then + filter = '(' .. filter .. ')' + end + parts[#parts + 1] = filter; + end + + parts[#parts + 1] = ')'; + + return tconcat(parts, ''); +end + +do + local ok, err; + + metronome.unlock_globals(); + ok, ldap = pcall(require, 'lualdap'); + metronome.lock_globals(); + if not ok then + module:log("error", "Failed to load the LuaLDAP library for accessing LDAP: %s", ldap); + module:log("error", "More information on install LuaLDAP can be found at http://www.keplerproject.org/lualdap"); + return; + end + + if not params then + module:log("error", "LDAP configuration required to use the LDAP storage module"); + return; + end + + ok, err = validate_config(); + + if not ok then + module:log("error", "LDAP configuration is invalid: %s", tostring(err)); + return; + end +end + +return _M; diff --git a/data/templates/metronome/modules/mod_auth_ldap2.lua b/data/templates/metronome/modules/mod_auth_ldap2.lua new file mode 100644 index 00000000..8c50a99f --- /dev/null +++ b/data/templates/metronome/modules/mod_auth_ldap2.lua @@ -0,0 +1,81 @@ +-- vim:sts=4 sw=4 + +-- Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- Copyright (C) 2012 Rob Hoelz +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- +-- http://code.google.com/p/prosody-modules/source/browse/mod_auth_ldap/mod_auth_ldap.lua +-- adapted to use common LDAP store + +local ldap = module:require 'ldap'; +local new_sasl = require 'util.sasl'.new; +local jsplit = require 'util.jid'.split; + +if not ldap then + return; +end + +local provider = {} + +function provider.test_password(username, password) + return ldap.bind(username, password); +end + +function provider.user_exists(username) + local params = ldap.getparams() + + local filter = ldap.filter.combine_and(params.user.filter, params.user.usernamefield .. '=' .. username); + if params.user.usernamefield == 'mail' then + filter = ldap.filter.combine_and(params.user.filter, 'mail=' .. username .. '@*'); + end + + return ldap.singlematch { + base = params.user.basedn, + filter = filter, + }; +end + +function provider.get_password(username) + return nil, "Passwords unavailable for LDAP."; +end + +function provider.set_password(username, password) + return nil, "Passwords unavailable for LDAP."; +end + +function provider.create_user(username, password) + return nil, "Account creation/modification not available with LDAP."; +end + +function provider.get_sasl_handler() + local testpass_authentication_profile = { + plain_test = function(sasl, username, password, realm) + return provider.test_password(username, password), true; + end, + mechanisms = { PLAIN = true }, + }; + return new_sasl(module.host, testpass_authentication_profile); +end + +function provider.is_admin(jid) + local admin_config = ldap.getparams().admin; + + if not admin_config then + return; + end + + local ld = ldap:getconnection(); + local username = jsplit(jid); + local filter = ldap.filter.combine_and(admin_config.filter, admin_config.namefield .. '=' .. username); + + return ldap.singlematch { + base = admin_config.basedn, + filter = filter, + }; +end + +module:provides("auth", provider); diff --git a/data/templates/metronome/modules/mod_legacyauth.lua b/data/templates/metronome/modules/mod_legacyauth.lua new file mode 100644 index 00000000..cee591c9 --- /dev/null +++ b/data/templates/metronome/modules/mod_legacyauth.lua @@ -0,0 +1,87 @@ +-- Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + + + +local st = require "util.stanza"; +local t_concat = table.concat; + +local secure_auth_only = module:get_option("c2s_require_encryption") + or module:get_option("require_encryption") + or not(module:get_option("allow_unencrypted_plain_auth")); + +local sessionmanager = require "core.sessionmanager"; +local usermanager = require "core.usermanager"; +local nodeprep = require "util.encodings".stringprep.nodeprep; +local resourceprep = require "util.encodings".stringprep.resourceprep; + +module:add_feature("jabber:iq:auth"); +module:hook("stream-features", function(event) + local origin, features = event.origin, event.features; + if secure_auth_only and not origin.secure then + -- Sorry, not offering to insecure streams! + return; + elseif not origin.username then + features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up(); + end +end); + +module:hook("stanza/iq/jabber:iq:auth:query", function(event) + local session, stanza = event.origin, event.stanza; + + if session.type ~= "c2s_unauthed" then + (session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections.")); + return true; + end + + if secure_auth_only and not session.secure then + session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server")); + return true; + end + + local username = stanza.tags[1]:child_with_name("username"); + local password = stanza.tags[1]:child_with_name("password"); + local resource = stanza.tags[1]:child_with_name("resource"); + if not (username and password and resource) then + local reply = st.reply(stanza); + session.send(reply:query("jabber:iq:auth") + :tag("username"):up() + :tag("password"):up() + :tag("resource"):up()); + else + username, password, resource = t_concat(username), t_concat(password), t_concat(resource); + username = nodeprep(username); + resource = resourceprep(resource) + if not (username and resource) then + session.send(st.error_reply(stanza, "modify", "bad-request")); + return true; + end + if usermanager.test_password(username, session.host, password) then + -- Authentication successful! + local success, err = sessionmanager.make_authenticated(session, username); + if success then + local err_type, err_msg; + success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource); + if not success then + session.send(st.error_reply(stanza, err_type, err, err_msg)); + session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager? + return true; + elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth + session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session.")); + session:close(); -- FIXME undo resource bind and auth instead of closing the session? + return true; + end + end + session.send(st.reply(stanza)); + else + session.send(st.error_reply(stanza, "auth", "not-authorized")); + end + end + return true; +end); + diff --git a/data/templates/metronome/modules/mod_storage_ldap.lua b/data/templates/metronome/modules/mod_storage_ldap.lua new file mode 100644 index 00000000..17850a21 --- /dev/null +++ b/data/templates/metronome/modules/mod_storage_ldap.lua @@ -0,0 +1,180 @@ +-- vim:sts=4 sw=4 + +-- Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- Copyright (C) 2012 Rob Hoelz +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + +---------------------------------------- +-- Constants and such -- +---------------------------------------- + +local setmetatable = setmetatable; +local ldap = module:require 'ldap'; +local vcardlib = module:require 'vcard'; +local st = require 'util.stanza'; +local gettime = require 'socket'.gettime; + +if not ldap then + return; +end + +local CACHE_EXPIRY = 300; +local params = module:get_option('ldap'); + +---------------------------------------- +-- Utility Functions -- +---------------------------------------- + +local function ldap_record_to_vcard(record) + return vcardlib.create { + record = record, + format = params.vcard_format, + } +end + +local get_alias_for_user; + +do + local user_cache; + local last_fetch_time; + + local function populate_user_cache() + local ld = ldap.getconnection(); + + local usernamefield = params.user.usernamefield; + local namefield = params.user.namefield; + + user_cache = {}; + + for _, attrs in ld:search { base = params.user.basedn, scope = 'onelevel', filter = params.user.filter } do + user_cache[attrs[usernamefield]] = attrs[namefield]; + end + last_fetch_time = gettime(); + end + + function get_alias_for_user(user) + if last_fetch_time and last_fetch_time + CACHE_EXPIRY < gettime() then + user_cache = nil; + end + if not user_cache then + populate_user_cache(); + end + return user_cache[user]; + end +end + +---------------------------------------- +-- General Setup -- +---------------------------------------- + +local ldap_store = {}; +ldap_store.__index = ldap_store; + +local adapters = { + roster = {}, + vcard = {}, +} + +for k, v in pairs(adapters) do + setmetatable(v, ldap_store); + v.__index = v; + v.name = k; +end + +function ldap_store:get(username) + return nil, "get method unimplemented on store '" .. tostring(self.name) .. "'" +end + +function ldap_store:set(username, data) + return nil, "LDAP storage is currently read-only"; +end + +---------------------------------------- +-- Roster Storage Implementation -- +---------------------------------------- + +function adapters.roster:get(username) + local ld = ldap.getconnection(); + local contacts = {}; + + local memberfield = params.groups.memberfield; + local namefield = params.groups.namefield; + local filter = memberfield .. '=' .. tostring(username); + + local groups = {}; + for _, config in ipairs(params.groups) do + groups[ config[namefield] ] = config.name; + end + + -- XXX this kind of relies on the way we do groups at INOC + for _, attrs in ld:search { base = params.groups.basedn, scope = 'onelevel', filter = filter } do + if groups[ attrs[namefield] ] then + local members = attrs[memberfield]; + + for _, user in ipairs(members) do + if user ~= username then + local jid = user .. '@' .. module.host; + local record = contacts[jid]; + + if not record then + record = { + subscription = 'both', + groups = {}, + name = get_alias_for_user(user), + }; + contacts[jid] = record; + end + + record.groups[ groups[ attrs[namefield] ] ] = true; + end + end + end + end + + return contacts; +end + +---------------------------------------- +-- vCard Storage Implementation -- +---------------------------------------- + +function adapters.vcard:get(username) + if not params.vcard_format then + return nil, ''; + end + + local ld = ldap.getconnection(); + local filter = params.user.usernamefield .. '=' .. tostring(username); + + local match = ldap.singlematch { + base = params.user.basedn, + filter = filter, + }; + if match then + match.jid = username .. '@' .. module.host + return st.preserialize(ldap_record_to_vcard(match)); + else + return nil, 'not found'; + end +end + +---------------------------------------- +-- Driver Definition -- +---------------------------------------- + +local driver = {}; + +function driver:open(store, typ) + local adapter = adapters[store]; + + if adapter and not typ then + return adapter; + end + return nil, "unsupported-store"; +end +module:provides("storage", driver); diff --git a/data/templates/metronome/modules/vcard.lib.lua b/data/templates/metronome/modules/vcard.lib.lua new file mode 100644 index 00000000..dcbd0106 --- /dev/null +++ b/data/templates/metronome/modules/vcard.lib.lua @@ -0,0 +1,162 @@ +-- vim:sts=4 sw=4 + +-- Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- Copyright (C) 2012 Rob Hoelz +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + +local st = require 'util.stanza'; + +local VCARD_NS = 'vcard-temp'; + +local builder_methods = {}; + +local base64_encode = require('util.encodings').base64.encode; + +function builder_methods:addvalue(key, value) + self.vcard:tag(key):text(value):up(); +end + +function builder_methods:addphotofield(tagname, format_section) + local record = self.record; + local format = self.format; + local vcard = self.vcard; + local config = format[format_section]; + + if not config then + return; + end + + if config.extval then + if record[config.extval] then + local tag = vcard:tag(tagname); + tag:tag('EXTVAL'):text(record[config.extval]):up(); + end + elseif config.type and config.binval then + if record[config.binval] then + local tag = vcard:tag(tagname); + tag:tag('TYPE'):text(config.type):up(); + tag:tag('BINVAL'):text(base64_encode(record[config.binval])):up(); + end + else + module:log('error', 'You have an invalid %s config section', tagname); + return; + end + + vcard:up(); +end + +function builder_methods:addregularfield(tagname, format_section) + local record = self.record; + local format = self.format; + local vcard = self.vcard; + + if not format[format_section] then + return; + end + + local tag = vcard:tag(tagname); + + for k, v in pairs(format[format_section]) do + tag:tag(string.upper(k)):text(record[v]):up(); + end + + vcard:up(); +end + +function builder_methods:addmultisectionedfield(tagname, format_section) + local record = self.record; + local format = self.format; + local vcard = self.vcard; + + if not format[format_section] then + return; + end + + for k, v in pairs(format[format_section]) do + local tag = vcard:tag(tagname); + + if type(k) == 'string' then + tag:tag(string.upper(k)):up(); + end + + for k2, v2 in pairs(v) do + if type(v2) == 'boolean' then + tag:tag(string.upper(k2)):up(); + else + tag:tag(string.upper(k2)):text(record[v2]):up(); + end + end + + vcard:up(); + end +end + +function builder_methods:build() + local record = self.record; + local format = self.format; + + self:addvalue( 'VERSION', '2.0'); + self:addvalue( 'FN', record[format.displayname]); + self:addregularfield( 'N', 'name'); + self:addvalue( 'NICKNAME', record[format.nickname]); + self:addphotofield( 'PHOTO', 'photo'); + self:addvalue( 'BDAY', record[format.birthday]); + self:addmultisectionedfield('ADR', 'address'); + self:addvalue( 'LABEL', nil); -- we don't support LABEL...yet. + self:addmultisectionedfield('TEL', 'telephone'); + self:addmultisectionedfield('EMAIL', 'email'); + self:addvalue( 'JABBERID', record.jid); + self:addvalue( 'MAILER', record[format.mailer]); + self:addvalue( 'TZ', record[format.timezone]); + self:addregularfield( 'GEO', 'geo'); + self:addvalue( 'TITLE', record[format.title]); + self:addvalue( 'ROLE', record[format.role]); + self:addphotofield( 'LOGO', 'logo'); + self:addvalue( 'AGENT', nil); -- we don't support AGENT...yet. + self:addregularfield( 'ORG', 'org'); + self:addvalue( 'CATEGORIES', nil); -- we don't support CATEGORIES...yet. + self:addvalue( 'NOTE', record[format.note]); + self:addvalue( 'PRODID', nil); -- we don't support PRODID...yet. + self:addvalue( 'REV', record[format.rev]); + self:addvalue( 'SORT-STRING', record[format.sortstring]); + self:addregularfield( 'SOUND', 'sound'); + self:addvalue( 'UID', record[format.uid]); + self:addvalue( 'URL', record[format.url]); + self:addvalue( 'CLASS', nil); -- we don't support CLASS...yet. + self:addregularfield( 'KEY', 'key'); + self:addvalue( 'DESC', record[format.description]); + + return self.vcard; +end + +local function new_builder(params) + local vcard_tag = st.stanza('vCard', { xmlns = VCARD_NS }); + + local object = { + vcard = vcard_tag, + __index = builder_methods, + }; + + for k, v in pairs(params) do + object[k] = v; + end + + setmetatable(object, object); + + return object; +end + +local _M = {}; + +function _M.create(params) + local builder = new_builder(params); + + return builder:build(); +end + +return _M; diff --git a/data/templates/mysql/my.cnf b/data/templates/mysql/my.cnf new file mode 100644 index 00000000..2d4e1df2 --- /dev/null +++ b/data/templates/mysql/my.cnf @@ -0,0 +1,89 @@ +# Example MySQL config file for small systems. +# +# This is for a system with little memory (<= 64M) where MySQL is only used +# from time to time and it's important that the mysqld daemon +# doesn't use much resources. +# +# MySQL programs look for option files in a set of +# locations which depend on the deployment platform. +# You can copy this option file to one of those +# locations. For information about these locations, see: +# http://dev.mysql.com/doc/mysql/en/option-files.html +# +# In this file, you can use all long options that a program supports. +# If you want to know which options a program supports, run the program +# with the "--help" option. + +# The following options will be passed to all MySQL clients +[client] +#password = your_password +port = 3306 +socket = /var/run/mysqld/mysqld.sock + +# Here follows entries for some specific programs + +# The MySQL server +[mysqld] +port = 3306 +socket = /var/run/mysqld/mysqld.sock +skip-external-locking +key_buffer_size = 16K +max_allowed_packet = 1M +table_open_cache = 4 +sort_buffer_size = 64K +read_buffer_size = 256K +read_rnd_buffer_size = 256K +net_buffer_length = 2K +thread_stack = 128K + +# Don't listen on a TCP/IP port at all. This can be a security enhancement, +# if all processes that need to connect to mysqld run on the same host. +# All interaction with mysqld must be made via Unix sockets or named pipes. +# Note that using this option without enabling named pipes on Windows +# (using the "enable-named-pipe" option) will render mysqld useless! +# +#skip-networking +server-id = 1 + +# Uncomment the following if you want to log updates +#log-bin=mysql-bin + +# binary logging format - mixed recommended +#binlog_format=mixed + +# Causes updates to non-transactional engines using statement format to be +# written directly to binary log. Before using this option make sure that +# there are no dependencies between transactional and non-transactional +# tables such as in the statement INSERT INTO t_myisam SELECT * FROM +# t_innodb; otherwise, slaves may diverge from the master. +#binlog_direct_non_transactional_updates=TRUE + +# Uncomment the following if you are using InnoDB tables +#innodb_data_home_dir = /var/lib/mysql +#innodb_data_file_path = ibdata1:10M:autoextend +#innodb_log_group_home_dir = /var/lib/mysql +# You can set .._buffer_pool_size up to 50 - 80 % +# of RAM but beware of setting memory usage too high +#innodb_buffer_pool_size = 16M +#innodb_additional_mem_pool_size = 2M +# Set .._log_file_size to 25 % of buffer pool size +#innodb_log_file_size = 5M +#innodb_log_buffer_size = 8M +#innodb_flush_log_at_trx_commit = 1 +#innodb_lock_wait_timeout = 50 + +[mysqldump] +quick +max_allowed_packet = 16M + +[mysql] +no-auto-rehash +# Remove the next comment character if you are not familiar with SQL +#safe-updates + +[myisamchk] +key_buffer_size = 8M +sort_buffer_size = 8M + +[mysqlhotcopy] +interactive-timeout diff --git a/data/templates/nginx/server.conf.j2 b/data/templates/nginx/server.conf.j2 new file mode 100644 index 00000000..656a1d80 --- /dev/null +++ b/data/templates/nginx/server.conf.j2 @@ -0,0 +1,46 @@ +server { + listen 80; + listen [::]:80; + server_name {{ domain }}; + + access_by_lua_file /usr/share/ssowat/access.lua; + + include conf.d/{{ domain }}.d/*.conf; + + location /yunohost/admin { + rewrite ^ https://$http_host$request_uri? permanent; + } + + access_log /var/log/nginx/{{ domain }}-access.log; + error_log /var/log/nginx/{{ domain }}-error.log; +} + +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name {{ domain }}; + ssl_certificate /etc/yunohost/certs/{{ domain }}/crt.pem; + ssl_certificate_key /etc/yunohost/certs/{{ domain }}/key.pem; + + ssl_session_timeout 5m; + ssl_session_cache shared:SSL:50m; + ssl_prefer_server_ciphers on; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!3DES:+HIGH:+MEDIUM; + add_header Strict-Transport-Security "max-age=31536000;"; + + # Uncomment the following directive after DH generation + # > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048 + + #ssl_dhparam /etc/ssl/private/dh2048.pem; + + access_by_lua_file /usr/share/ssowat/access.lua; + + include conf.d/{{ domain }}.d/*.conf; + + include conf.d/yunohost_admin.conf.inc; + include conf.d/yunohost_api.conf.inc; + + access_log /var/log/nginx/{{ domain }}-access.log; + error_log /var/log/nginx/{{ domain }}-error.log; +} diff --git a/data/templates/nginx/ssowat.conf b/data/templates/nginx/ssowat.conf new file mode 100644 index 00000000..c82cd40e --- /dev/null +++ b/data/templates/nginx/ssowat.conf @@ -0,0 +1,3 @@ +lua_shared_dict cache 10m; +init_by_lua_file /usr/share/ssowat/init.lua; +server_names_hash_bucket_size 64; diff --git a/data/templates/nginx/yunohost_admin.conf b/data/templates/nginx/yunohost_admin.conf new file mode 100644 index 00000000..0f208cb5 --- /dev/null +++ b/data/templates/nginx/yunohost_admin.conf @@ -0,0 +1,35 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + location / { + rewrite ^ https://$http_host/yunohost/admin permanent; + } + location /yunohost/admin { + rewrite ^ https://$http_host$request_uri? permanent; + } +} +server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/yunohost/certs/yunohost.org/crt.pem; + ssl_certificate_key /etc/yunohost/certs/yunohost.org/key.pem; + ssl_session_timeout 5m; + ssl_session_cache shared:SSL:50m; + ssl_prefer_server_ciphers on; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!3DES:+HIGH:+MEDIUM; + add_header Strict-Transport-Security "max-age=31536000;"; + + location / { + rewrite ^ https://$http_host/yunohost/admin permanent; + } + + # Block crawlers bot + location /yunohost { + if ($http_user_agent ~ (crawl|Googlebot|Slurp|spider|bingbot|tracker|click|parser|spider|facebookexternalhit) ) { + return 403; + } + } + include conf.d/yunohost_admin.conf.inc; + include conf.d/yunohost_api.conf.inc; +} diff --git a/data/templates/nginx/yunohost_admin.conf.inc b/data/templates/nginx/yunohost_admin.conf.inc new file mode 100644 index 00000000..73610294 --- /dev/null +++ b/data/templates/nginx/yunohost_admin.conf.inc @@ -0,0 +1,5 @@ +location /yunohost/admin { + alias /usr/share/yunohost/admin/; + default_type text/html; + index index.html; +} diff --git a/data/templates/nginx/yunohost_api.conf.inc b/data/templates/nginx/yunohost_api.conf.inc new file mode 100644 index 00000000..307eb4aa --- /dev/null +++ b/data/templates/nginx/yunohost_api.conf.inc @@ -0,0 +1,7 @@ +location /yunohost/api/ { + proxy_read_timeout 3600s; + proxy_pass http://127.0.0.1:6787/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; +} diff --git a/data/templates/nginx/yunohost_local.conf b/data/templates/nginx/yunohost_local.conf new file mode 100644 index 00000000..ebf2bd65 --- /dev/null +++ b/data/templates/nginx/yunohost_local.conf @@ -0,0 +1 @@ +server_name $server_name yunohost.local; diff --git a/data/templates/nginx/yunohost_panel.conf.inc b/data/templates/nginx/yunohost_panel.conf.inc new file mode 100644 index 00000000..4d5b441d --- /dev/null +++ b/data/templates/nginx/yunohost_panel.conf.inc @@ -0,0 +1,2 @@ +sub_filter ''; +sub_filter_once on; diff --git a/data/templates/nslcd/nslcd.conf b/data/templates/nslcd/nslcd.conf new file mode 100644 index 00000000..b2daf777 --- /dev/null +++ b/data/templates/nslcd/nslcd.conf @@ -0,0 +1,32 @@ +root@65ba01d0c078:/usr/share/yunohost/yunohost-config/slapd# cat /etc/nslcd.conf +# /etc/nslcd.conf +# nslcd configuration file. See nslcd.conf(5) +# for details. + +# The user and group nslcd should run as. +uid nslcd +gid nslcd + +# The location at which the LDAP server(s) should be reachable. +uri ldap://localhost/ + +# The search base that will be used for all queries. +base dc=yunohost,dc=org + +# The LDAP protocol version to use. +#ldap_version 3 + +# The DN to bind with for normal lookups. +#binddn +#bindpw + +# The DN used for password modifications by root. +#rootpwmoddn cn=admin,dc=example,dc=com + +# SSL options +#ssl off +#tls_reqcert + +# The search scope. +#scope sub + diff --git a/data/templates/postfix/header_check b/data/templates/postfix/header_check new file mode 100644 index 00000000..bf5c3352 --- /dev/null +++ b/data/templates/postfix/header_check @@ -0,0 +1,4 @@ +/^X-Originating-IP:/ IGNORE +/^Received:/ IGNORE +/^User-Agent:/ IGNORE +/^X-Mailer:/ IGNORE diff --git a/data/templates/postfix/ldap-accounts.cf b/data/templates/postfix/ldap-accounts.cf new file mode 100644 index 00000000..bd3576de --- /dev/null +++ b/data/templates/postfix/ldap-accounts.cf @@ -0,0 +1,5 @@ +server_host = localhost +server_port = 389 +search_base = dc=yunohost,dc=org +query_filter = (&(objectClass=mailAccount)(mail=%s)) +result_attribute = uid diff --git a/data/templates/postfix/ldap-aliases.cf b/data/templates/postfix/ldap-aliases.cf new file mode 100644 index 00000000..a9ef52cf --- /dev/null +++ b/data/templates/postfix/ldap-aliases.cf @@ -0,0 +1,5 @@ +server_host = localhost +server_port = 389 +search_base = dc=yunohost,dc=org +query_filter = (&(objectClass=mailAccount)(mail=%s)) +result_attribute = maildrop diff --git a/data/templates/postfix/ldap-domains.cf b/data/templates/postfix/ldap-domains.cf new file mode 100644 index 00000000..088640bf --- /dev/null +++ b/data/templates/postfix/ldap-domains.cf @@ -0,0 +1,5 @@ +server_host = localhost +server_port = 389 +search_base = ou=domains,dc=yunohost,dc=org +query_filter = (&(objectClass=mailDomain)(virtualdomain=%s)) +result_attribute = virtualdomain diff --git a/data/templates/postfix/main.cf-ipv4.j2 b/data/templates/postfix/main.cf-ipv4.j2 new file mode 100644 index 00000000..f2cf0457 --- /dev/null +++ b/data/templates/postfix/main.cf-ipv4.j2 @@ -0,0 +1,127 @@ +# See /usr/share/postfix/main.cf.dist for a commented, more complete version + + +# Debian specific: Specifying a file name will cause the first +# line of that file to be used as the name. The Debian default +# is /etc/mailname. +#myorigin = /etc/mailname + +smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) +biff = no + +# appending .domain is the MUA's job. +append_dot_mydomain = no + +# Uncomment the next line to generate "delayed mail" warnings +#delay_warning_time = 4h + +readme_directory = no + +# TLS parameters +smtpd_tls_cert_file=/etc/ssl/certs/yunohost_crt.pem +smtpd_tls_key_file=/etc/ssl/private/yunohost_key.pem +smtpd_tls_CAfile = /etc/ssl/certs/ca-yunohost_crt.pem +smtpd_use_tls=yes +smtpd_tls_exclude_ciphers = aNULL, MD5, DES, ADH +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache +smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache + +# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for +# information on enabling SSL in the smtp client. + +myhostname = {{ domain }} +alias_maps = hash:/etc/aliases +alias_database = hash:/etc/aliases +mydomain = {{ domain }} +mydestination = localhost +relayhost = +mynetworks = 127.0.0.0/8 +mailbox_command = procmail -a "$EXTENSION" +mailbox_size_limit = 0 +recipient_delimiter = + +inet_interfaces = all +inet_protocols = ipv4 + +#### add yunohost #### +message_size_limit = 10240000 + +# Virtual Domains Control +virtual_mailbox_domains = ldap:/etc/postfix/ldap-domains.cf +virtual_mailbox_maps = ldap:/etc/postfix/ldap-accounts.cf +virtual_mailbox_base = +virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf +virtual_alias_domains = +virtual_minimum_uid = 100 +virtual_uid_maps = static:vmail +virtual_gid_maps = static:mail + +# Dovecot LDA +virtual_transport = dovecot +dovecot_destination_recipient_limit = 1 + +# Enable SASL authentication for the smtpd daemon +smtpd_sasl_auth_enable = yes +smtpd_sasl_type = dovecot +smtpd_sasl_path = private/auth +# Fix some outlook's bugs +broken_sasl_auth_clients = yes +# Reject anonymous connections +smtpd_sasl_security_options = noanonymous +smtpd_sasl_local_domain = + + +# Use AMaVis +content_filter = amavis:[127.0.0.1]:10024 + +# Wait until the RCPT TO command before evaluating restrictions +smtpd_delay_reject = yes + +# Basics Restrictions +smtpd_helo_required = yes +strict_rfc821_envelopes = yes + +# Requirements for the connecting server +smtpd_client_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_rbl_client bl.spamcop.net, + reject_rbl_client cbl.abuseat.org, + reject_rbl_client sbl-xbl.spamhaus.org, + permit + +# Requirements for the HELO statement +smtpd_helo_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_non_fqdn_hostname, + reject_invalid_hostname, + permit + +# Requirements for the sender address +smtpd_sender_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_non_fqdn_sender, + reject_unknown_sender_domain, + permit + +# Requirement for the recipient address +smtpd_recipient_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_non_fqdn_recipient, + reject_unknown_recipient_domain, + reject_unauth_destination, + check_policy_service unix:private/policy-spf + check_policy_service inet:127.0.0.1:10023 + permit + +# Use SPF +policy-spf_time_limit = 3600s + +# SRS +sender_canonical_maps = regexp:/etc/postfix/sender_canonical +sender_canonical_classes = envelope_sender + +# Ignore some headers +smtp_header_checks = regexp:/etc/postfix/header_checks diff --git a/data/templates/postfix/main.cf.j2 b/data/templates/postfix/main.cf.j2 new file mode 100644 index 00000000..6c1052dc --- /dev/null +++ b/data/templates/postfix/main.cf.j2 @@ -0,0 +1,126 @@ +# See /usr/share/postfix/main.cf.dist for a commented, more complete version + + +# Debian specific: Specifying a file name will cause the first +# line of that file to be used as the name. The Debian default +# is /etc/mailname. +#myorigin = /etc/mailname + +smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) +biff = no + +# appending .domain is the MUA's job. +append_dot_mydomain = no + +# Uncomment the next line to generate "delayed mail" warnings +#delay_warning_time = 4h + +readme_directory = no + +# TLS parameters +smtpd_tls_cert_file=/etc/ssl/certs/yunohost_crt.pem +smtpd_tls_key_file=/etc/ssl/private/yunohost_key.pem +smtpd_tls_CAfile = /etc/ssl/certs/ca-yunohost_crt.pem +smtpd_use_tls=yes +smtpd_tls_exclude_ciphers = aNULL, MD5, DES, ADH +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache +smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache + +# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for +# information on enabling SSL in the smtp client. + +myhostname = {{ domain }} +alias_maps = hash:/etc/aliases +alias_database = hash:/etc/aliases +mydomain = {{ domain }} +mydestination = localhost +relayhost = +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 +mailbox_command = procmail -a "$EXTENSION" +mailbox_size_limit = 0 +recipient_delimiter = + +inet_interfaces = all + +#### add yunohost #### +message_size_limit = 10240000 + +# Virtual Domains Control +virtual_mailbox_domains = ldap:/etc/postfix/ldap-domains.cf +virtual_mailbox_maps = ldap:/etc/postfix/ldap-accounts.cf +virtual_mailbox_base = +virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf +virtual_alias_domains = +virtual_minimum_uid = 100 +virtual_uid_maps = static:vmail +virtual_gid_maps = static:mail + +# Dovecot LDA +virtual_transport = dovecot +dovecot_destination_recipient_limit = 1 + +# Enable SASL authentication for the smtpd daemon +smtpd_sasl_auth_enable = yes +smtpd_sasl_type = dovecot +smtpd_sasl_path = private/auth +# Fix some outlook's bugs +broken_sasl_auth_clients = yes +# Reject anonymous connections +smtpd_sasl_security_options = noanonymous +smtpd_sasl_local_domain = + + +# Use AMaVis +content_filter = amavis:[127.0.0.1]:10024 + +# Wait until the RCPT TO command before evaluating restrictions +smtpd_delay_reject = yes + +# Basics Restrictions +smtpd_helo_required = yes +strict_rfc821_envelopes = yes + +# Requirements for the connecting server +smtpd_client_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_rbl_client bl.spamcop.net, + reject_rbl_client cbl.abuseat.org, + reject_rbl_client sbl-xbl.spamhaus.org, + permit + +# Requirements for the HELO statement +smtpd_helo_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_non_fqdn_hostname, + reject_invalid_hostname, + permit + +# Requirements for the sender address +smtpd_sender_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_non_fqdn_sender, + reject_unknown_sender_domain, + permit + +# Requirement for the recipient address +smtpd_recipient_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_non_fqdn_recipient, + reject_unknown_recipient_domain, + reject_unauth_destination, + check_policy_service unix:private/policy-spf + check_policy_service inet:127.0.0.1:10023 + permit + +#Use SPF +policy-spf_time_limit = 3600s + +# SRS +sender_canonical_maps = regexp:/etc/postfix/sender_canonical +sender_canonical_classes = envelope_sender + +# Ignore some headers +smtp_header_checks = regexp:/etc/postfix/header_checks diff --git a/data/templates/postfix/master.cf b/data/templates/postfix/master.cf new file mode 100644 index 00000000..9ced2569 --- /dev/null +++ b/data/templates/postfix/master.cf @@ -0,0 +1,147 @@ +# +# Postfix master process configuration file. For details on the format +# of the file, see the master(5) manual page (command: "man 5 master"). +# +# Do not forget to execute "postfix reload" after editing this file. +# +# ========================================================================== +# service type private unpriv chroot wakeup maxproc command + args +# (yes) (yes) (yes) (never) (100) +# ========================================================================== +smtp inet n - - - - smtpd +#submission inet n - - - - smtpd +# -o smtpd_tls_security_level=encrypt +# -o smtpd_sasl_auth_enable=yes +# -o smtpd_client_restrictions=permit_sasl_authenticated,reject +# -o milter_macro_daemon_name=ORIGINATING +smtps inet n - - - - smtpd + -o header_checks=pcre:/etc/postfix/header_checks + -o smtpd_tls_wrappermode=yes + -o smtpd_sasl_auth_enable=yes +# -o smtpd_client_restrictions=permit_sasl_authenticated,reject +# -o milter_macro_daemon_name=ORIGINATING +#628 inet n - - - - qmqpd +pickup fifo n - - 60 1 pickup +cleanup unix n - - - 0 cleanup +qmgr fifo n - n 300 1 qmgr +#qmgr fifo n - - 300 1 oqmgr +tlsmgr unix - - - 1000? 1 tlsmgr +rewrite unix - - - - - trivial-rewrite +bounce unix - - - - 0 bounce +defer unix - - - - 0 bounce +trace unix - - - - 0 bounce +verify unix - - - - 1 verify +flush unix n - - 1000? 0 flush +proxymap unix - - n - - proxymap +proxywrite unix - - n - 1 proxymap +smtp unix - - - - - smtp +# When relaying mail as backup MX, disable fallback_relay to avoid MX loops +relay unix - - - - - smtp + -o smtp_fallback_relay= +# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 +showq unix n - - - - showq +error unix - - - - - error +retry unix - - - - - error +discard unix - - - - - discard +local unix - n n - - local +virtual unix - n n - - virtual +lmtp unix - - - - - lmtp +anvil unix - - - - 1 anvil +scache unix - - - - 1 scache +# +# ==================================================================== +# Interfaces to non-Postfix software. Be sure to examine the manual +# pages of the non-Postfix software to find out what options it wants. +# +# Many of the following services use the Postfix pipe(8) delivery +# agent. See the pipe(8) man page for information about ${recipient} +# and other message envelope options. +# ==================================================================== +# +# maildrop. See the Postfix MAILDROP_README file for details. +# Also specify in main.cf: maildrop_destination_recipient_limit=1 +# +maildrop unix - n n - - pipe + flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient} +# +# ==================================================================== +# +# Recent Cyrus versions can use the existing "lmtp" master.cf entry. +# +# Specify in cyrus.conf: +# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4 +# +# Specify in main.cf one or more of the following: +# mailbox_transport = lmtp:inet:localhost +# virtual_transport = lmtp:inet:localhost +# +# ==================================================================== +# +# Cyrus 2.1.5 (Amos Gouaux) +# Also specify in main.cf: cyrus_destination_recipient_limit=1 +# +#cyrus unix - n n - - pipe +# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user} +# +# ==================================================================== +# Old example of delivery via Cyrus. +# +#old-cyrus unix - n n - - pipe +# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user} +# +# ==================================================================== +# +# See the Postfix UUCP_README file for configuration details. +# +uucp unix - n n - - pipe + flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) +# +# Other external delivery methods. +# +ifmail unix - n n - - pipe + flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient) +bsmtp unix - n n - - pipe + flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient +scalemail-backend unix - n n - 2 pipe + flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension} +mailman unix - n n - - pipe + flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py + ${nexthop} ${user} + +# Dovecot LDA +dovecot unix - n n - - pipe + flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop} -m ${extension} +# ========================================================================== +# service type private unpriv chroot wakeup maxproc command + args +# (yes) (yes) (yes) (never) (100) +# ========================================================================== +# Added using postfix-add-filter script: +amavis unix - - - - 2 smtp + -o smtp_data_done_timeout=1200 + -o smtp_send_xforward_command=yes + -o smtp_tls_note_starttls_offer=no + +policy-spf unix - n n - - spawn + user=nobody argv=/usr/bin/perl /usr/sbin/postfix-policyd-spf-perl + +127.0.0.1:10025 inet n - - - - smtpd + -o content_filter= + -o smtpd_delay_reject=no + -o smtpd_client_restrictions=permit_mynetworks,reject + -o smtpd_helo_restrictions= + -o smtpd_sender_restrictions= + -o smtpd_recipient_restrictions=permit_mynetworks,reject + -o smtpd_data_restrictions=reject_unauth_pipelining + -o smtpd_end_of_data_restrictions= + -o smtpd_restriction_classes= + -o mynetworks=127.0.0.0/8 + -o smtpd_error_sleep_time=0 + -o smtpd_soft_error_limit=1001 + -o smtpd_hard_error_limit=1000 + -o smtpd_client_connection_count_limit=0 + -o smtpd_client_connection_rate_limit=0 + -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters + -o local_header_rewrite_clients= + -o smtpd_milters= + -o local_recipient_maps= + -o relay_recipient_maps= diff --git a/data/templates/postfix/postgrey b/data/templates/postfix/postgrey new file mode 100644 index 00000000..1af70c14 --- /dev/null +++ b/data/templates/postfix/postgrey @@ -0,0 +1,12 @@ +# postgrey startup options, created for Debian + +# you may want to set +# --delay=N how long to greylist, seconds (default: 300) +# --max-age=N delete old entries after N days (default: 35) +# see also the postgrey(8) manpage + +POSTGREY_OPTS="--inet=10023 --delay=30" + +# the --greylist-text commandline argument can not be easily passed through +# POSTGREY_OPTS when it contains spaces. So, insert your text here: +#POSTGREY_TEXT="Your customized rejection message here" diff --git a/data/templates/postfix/sender_canonical b/data/templates/postfix/sender_canonical new file mode 100644 index 00000000..caf093d1 --- /dev/null +++ b/data/templates/postfix/sender_canonical @@ -0,0 +1 @@ +/^(.*)@(.*)$/ ${1} diff --git a/data/templates/slapd/mailserver.schema b/data/templates/slapd/mailserver.schema new file mode 100644 index 00000000..55374ce4 --- /dev/null +++ b/data/templates/slapd/mailserver.schema @@ -0,0 +1,87 @@ +## LDAP Schema Yunohost EMAIL +## Version 0.1 +## Adrien Beudin + +# Attributes +attributetype ( 1.3.6.1.4.1.40328.1.20.2.1 + NAME 'maildrop' + DESC 'Mail addresses where mails are forwarded -- ie forwards' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) + +attributetype ( 1.3.6.1.4.1.40328.1.20.2.2 + NAME 'mailalias' + DESC 'Mail addresses accepted by this account -- ie aliases' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) + +attributetype ( 1.3.6.1.4.1.40328.1.20.2.3 + NAME 'mailenable' + DESC 'Mail Account validity' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{8}) + +attributetype ( 1.3.6.1.4.1.40328.1.20.2.4 + NAME 'mailbox' + DESC 'Mailbox path where mails are delivered' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) + +attributetype ( 1.3.6.1.4.1.40328.1.20.2.5 + NAME 'virtualdomain' + DESC 'A mail domain name' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) + +attributetype ( 1.3.6.1.4.1.40328.1.20.2.6 + NAME 'virtualdomaindescription' + DESC 'Virtual domain description' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) + +attributetype ( 1.3.6.1.4.1.40328.1.20.2.7 + NAME 'mailuserquota' + DESC 'Mailbox quota for a user in kilo-bytes' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +# Mail Account Objectclass +objectclass ( 1.3.6.1.4.1.40328.1.1.2.1 + NAME 'mailAccount' + DESC 'Mail Account' + SUP top + AUXILIARY + MUST ( + mail + ) + MAY ( + mailalias $ maildrop $ mailenable $ mailbox $ mailuserquota + ) + ) + +# Mail Domain Objectclass +objectclass ( 1.3.6.1.4.1.40328.1.1.2.2 + NAME 'mailDomain' + DESC 'Domain mail entry' + SUP top + STRUCTURAL + MUST ( + virtualdomain + ) + MAY ( + virtualdomaindescription $ mailuserquota + ) + ) + +# Mail Group Objectclass +objectclass ( 1.3.6.1.4.1.40328.1.1.2.3 + NAME 'mailGroup' SUP top AUXILIARY + DESC 'Mail Group' + MUST ( mail ) + ) diff --git a/data/templates/slapd/slapd.conf b/data/templates/slapd/slapd.conf new file mode 100644 index 00000000..3b0e3cf2 --- /dev/null +++ b/data/templates/slapd/slapd.conf @@ -0,0 +1,143 @@ +# This is the main slapd configuration file. See slapd.conf(5) for more +# info on the configuration options. + +####################################################################### +# Global Directives: + +# Features to permit +#allow bind_v2 + +# Schema and objectClass definitions +include /etc/ldap/schema/core.schema +include /etc/ldap/schema/cosine.schema +include /etc/ldap/schema/nis.schema +include /etc/ldap/schema/inetorgperson.schema +include /etc/ldap/schema/mailserver.schema +include /etc/ldap/schema/sudo.schema +include /etc/ldap/schema/samba.schema + +# Where the pid file is put. The init.d script +# will not stop the server if you change this. +pidfile /var/run/slapd/slapd.pid + +# List of arguments that were passed to the server +argsfile /var/run/slapd/slapd.args + +password-hash {SSHA} + +# Read slapd.conf(5) for possible values +loglevel 256 + +# Where the dynamically loaded modules are stored +modulepath /usr/lib/ldap +moduleload back_hdb +moduleload memberof + +# The maximum number of entries that is returned for a search operation +sizelimit 500 + +# The tool-threads parameter sets the actual amount of cpu's that is used +# for indexing. +tool-threads 1 + +####################################################################### +# Specific Backend Directives for hdb: +# Backend specific directives apply to this backend until another +# 'backend' directive occurs +backend hdb + +####################################################################### +# Specific Backend Directives for 'other': +# Backend specific directives apply to this backend until another +# 'backend' directive occurs +#backend + +####################################################################### +# Specific Directives for database #1, of type hdb: +# Database specific directives apply to this databasse until another +# 'database' directive occurs +database hdb + +# The base of your directory in database #1 +suffix "dc=yunohost,dc=org" + +directory "/var/lib/ldap" + +# The dbconfig settings are used to generate a DB_CONFIG file the first +# time slapd starts. They do NOT override existing an existing DB_CONFIG +# file. You should therefore change these settings in DB_CONFIG directly +# or remove DB_CONFIG and restart slapd for changes to take effect. + +# For the Debian package we use 2MB as default but be sure to update this +# value if you have plenty of RAM +dbconfig set_cachesize 0 2097152 0 + +# Sven Hartge reported that he had to set this value incredibly high +# to get slapd running at all. See http://bugs.debian.org/303057 for more +# information. + +# Number of objects that can be locked at the same time. +dbconfig set_lk_max_objects 1500 +# Number of locks (both requested and granted) +dbconfig set_lk_max_locks 1500 +# Number of lockers +dbconfig set_lk_max_lockers 1500 + +# Indexing options for database #1 +index objectClass eq +index uid eq,sub +index entryCSN,entryUUID eq + +# Save the time that the entry gets modified, for database #1 +lastmod on + +# Checkpoint the BerkeleyDB database periodically in case of system +# failure and to speed slapd shutdown. +checkpoint 512 30 + +# Where to store the replica logs for database #1 +# replogfile /var/lib/ldap/replog + +# The userPassword by default can be changed +# by the entry owning it if they are authenticated. +# Others should not be able to see it, except the +# admin entry below +# These access lines apply to database #1 only +access to attrs=userPassword + by dn="cn=admin,dc=yunohost,dc=org" write + by anonymous auth + by self write + by * none + +access to attrs=cn,gecos,givenName,mail,maildrop,displayName,sn + by dn="cn=admin,dc=yunohost,dc=org" write + by self write + by * read + + +# Ensure read access to the base for things like +# supportedSASLMechanisms. Without this you may +# have problems with SASL not knowing what +# mechanisms are available and the like. +# Note that this is covered by the 'access to *' +# ACL below too but if you change that as people +# are wont to do you'll still need this if you +# want SASL (and possible other things) to work +# happily. +access to dn.base="" by * read + +# The admin dn has full write access, everyone else +# can read everything. +access to * + by dn="cn=admin,dc=yunohost,dc=org" write + by group/groupOfNames/Member="cn=admin,ou=groups,dc=yunohost,dc=org" write + by * read + +####################################################################### +# Specific Directives for database #2, of type 'other' (can be hdb too): +# Database specific directives apply to this databasse until another +# 'database' directive occurs +#database + +# The base of your directory for database #2 +#suffix "dc=debian,dc=org" diff --git a/data/templates/slapd/slapd.default b/data/templates/slapd/slapd.default new file mode 100644 index 00000000..9cd3b2e9 --- /dev/null +++ b/data/templates/slapd/slapd.default @@ -0,0 +1,45 @@ +# Default location of the slapd.conf file or slapd.d cn=config directory. If +# empty, use the compiled-in default (/etc/ldap/slapd.d with a fallback to +# /etc/ldap/slapd.conf). +SLAPD_CONF=/etc/ldap/slapd.conf + +# System account to run the slapd server under. If empty the server +# will run as root. +SLAPD_USER="openldap" + +# System group to run the slapd server under. If empty the server will +# run in the primary group of its user. +SLAPD_GROUP="openldap" + +# Path to the pid file of the slapd server. If not set the init.d script +# will try to figure it out from $SLAPD_CONF (/etc/ldap/slapd.conf by +# default) +SLAPD_PIDFILE= + +# slapd normally serves ldap only on all TCP-ports 389. slapd can also +# service requests on TCP-port 636 (ldaps) and requests via unix +# sockets. +# Example usage: +# SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///" +SLAPD_SERVICES="ldap://127.0.0.1/ ldapi://127.0.0.1/" + +# If SLAPD_NO_START is set, the init script will not start or restart +# slapd (but stop will still work). Uncomment this if you are +# starting slapd via some other means or if you don't want slapd normally +# started at boot. +#SLAPD_NO_START=1 + +# If SLAPD_SENTINEL_FILE is set to path to a file and that file exists, +# the init script will not start or restart slapd (but stop will still +# work). Use this for temporarily disabling startup of slapd (when doing +# maintenance, for example, or through a configuration management system) +# when you don't want to edit a configuration file. +SLAPD_SENTINEL_FILE=/etc/ldap/noslapd + +# For Kerberos authentication (via SASL), slapd by default uses the system +# keytab file (/etc/krb5.keytab). To use a different keytab file, +# uncomment this line and change the path. +#export KRB5_KTNAME=/etc/krb5.keytab + +# Additional options to pass to slapd +SLAPD_OPTIONS="" diff --git a/data/templates/spamassassin/local.cf b/data/templates/spamassassin/local.cf new file mode 100644 index 00000000..bc37b3a6 --- /dev/null +++ b/data/templates/spamassassin/local.cf @@ -0,0 +1,94 @@ +# This is the right place to customize your installation of SpamAssassin. +report_safe 0 +lock_method flock + +# Bayes-related operations +use_bayes 1 +use_bayes_rules 1 +bayes_auto_learn 1 +bayes_auto_expire 1 +bayes_path /var/lib/amavis/.spamassassin/bayes +bayes_file_mode 0777 + +# External network tests +dns_available yes +skip_rbl_checks 0 +use_razor2 1 +use_pyzor 1 + +# Use URIBL (http://www.uribl.com/about.shtml) +urirhssub URIBL_BLACK multi.uribl.com. A 2 +body URIBL_BLACK eval:check_uridnsbl('URIBL_BLACK') +describe URIBL_BLACK Contains an URL listed in the URIBL blacklist +tflags URIBL_BLACK net +score URIBL_BLACK 3.0 + +urirhssub URIBL_GREY multi.uribl.com. A 4 +body URIBL_GREY eval:check_uridnsbl('URIBL_GREY') +describe URIBL_GREY Contains an URL listed in the URIBL greylist +tflags URIBL_GREY net +score URIBL_GREY 0.25 + +# Use SURBL (http://www.surbl.org/) +urirhssub URIBL_JP_SURBL multi.surbl.org. A 64 +body URIBL_JP_SURBL eval:check_uridnsbl('URIBL_JP_SURBL') +describe URIBL_JP_SURBL Has URI in JP at http://www.surbl.org/lists.html +tflags URIBL_JP_SURBL net +score URIBL_JP_SURBL 3.0 + + +score SPF_FAIL 10.000 +score SPF_HELO_FAIL 10.000 +score RAZOR2_CHECK 2.500 +score RAZOR2_CF_RANGE_51_100 3.500 +# +# See 'perldoc Mail::SpamAssassin::Conf' for details of what can be +# tweaked. +# +# Only a small subset of options are listed below +# +########################################################################### + +# Add *****SPAM***** to the Subject header of spam e-mails +# +# rewrite_header Subject *****SPAM***** + + +# Save spam messages as a message/rfc822 MIME attachment instead of +# modifying the original message (0: off, 2: use text/plain instead) +# +# report_safe 1 + + +# Set which networks or hosts are considered 'trusted' by your mail +# server (i.e. not spammers) +# +# trusted_networks 212.17.35. + + +# Set file-locking method (flock is not safe over NFS, but is faster) +# +# lock_method flock + + +# Set the threshold at which a message is considered spam (default: 5.0) +# +# required_score 5.0 + + +# Use Bayesian classifier (default: 1) +# +# use_bayes 1 + + +# Bayesian classifier auto-learning (default: 1) +# +# bayes_auto_learn 1 + + +# Set headers which may provide inappropriate cues to the Bayesian +# classifier +# +# bayes_ignore_header X-Bogosity +# bayes_ignore_header X-Spam-Flag +# bayes_ignore_header X-Spam-Status diff --git a/data/templates/spamassassin/spamassassin.default b/data/templates/spamassassin/spamassassin.default new file mode 100644 index 00000000..da1b3311 --- /dev/null +++ b/data/templates/spamassassin/spamassassin.default @@ -0,0 +1,31 @@ +# /etc/default/spamassassin +# Duncan Findlay + +# WARNING: please read README.spamd before using. +# There may be security risks. + +# Change to one to enable spamd +ENABLED=0 + +# Options +# See man spamd for possible options. The -d option is automatically added. + +# SpamAssassin uses a preforking model, so be careful! You need to +# make sure --max-children is not set to anything higher than 5, +# unless you know what you're doing. + +OPTIONS="--create-prefs --max-children 5 --helper-home-dir" + +# Pid file +# Where should spamd write its PID to file? If you use the -u or +# --username option above, this needs to be writable by that user. +# Otherwise, the init script will not be able to shut spamd down. +PIDFILE="/var/run/spamd.pid" + +# Set nice level of spamd +#NICE="--nicelevel 15" + +# Cronjob +# Set to anything but 0 to enable the cron job to automatically update +# spamassassin's rules on a nightly basis +CRON=1 diff --git a/data/templates/ssh/sshd_config b/data/templates/ssh/sshd_config new file mode 100644 index 00000000..695ea0d3 --- /dev/null +++ b/data/templates/ssh/sshd_config @@ -0,0 +1,93 @@ +# Package generated configuration file +# See the sshd_config(5) manpage for details + +# What ports, IPs and protocols we listen for +Port 22 +# Use these options to restrict which interfaces/protocols sshd will bind to +ListenAddress :: +ListenAddress 0.0.0.0 +Protocol 2 +# HostKeys for protocol version 2 +HostKey /etc/ssh/ssh_host_rsa_key +HostKey /etc/ssh/ssh_host_dsa_key +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 768 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 120 +PermitRootLogin no +StrictModes yes + +RSAAuthentication yes +PubkeyAuthentication yes +#AuthorizedKeysFile %h/.ssh/authorized_keys + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts yes +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication no +# similar for protocol version 2 +HostbasedAuthentication no +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords no + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication no + +# Change to no to disable tunnelled clear text passwords +#PasswordAuthentication yes + +# Kerberos options +#KerberosAuthentication no +#KerberosGetAFSToken no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes + +X11Forwarding yes +X11DisplayOffset 10 +PrintMotd no +PrintLastLog yes +TCPKeepAlive yes +#UseLogin no + +#MaxStartups 10:30:60 +Banner /etc/issue.net + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +Subsystem sftp internal-sftp + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM yes + +Match User sftpusers + ForceCommand internal-sftp + ChrootDirectory /home/%u + AllowTcpForwarding no + GatewayPorts no + X11Forwarding no diff --git a/data/templates/ssh/sshd_config-ipv4 b/data/templates/ssh/sshd_config-ipv4 new file mode 100644 index 00000000..1545b607 --- /dev/null +++ b/data/templates/ssh/sshd_config-ipv4 @@ -0,0 +1,93 @@ +# Package generated configuration file +# See the sshd_config(5) manpage for details + +# What ports, IPs and protocols we listen for +Port 22 +# Use these options to restrict which interfaces/protocols sshd will bind to +#ListenAddress :: +ListenAddress 0.0.0.0 +Protocol 2 +# HostKeys for protocol version 2 +HostKey /etc/ssh/ssh_host_rsa_key +HostKey /etc/ssh/ssh_host_dsa_key +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 768 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 120 +PermitRootLogin no +StrictModes yes + +RSAAuthentication yes +PubkeyAuthentication yes +#AuthorizedKeysFile %h/.ssh/authorized_keys + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts yes +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication no +# similar for protocol version 2 +HostbasedAuthentication no +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords no + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication no + +# Change to no to disable tunnelled clear text passwords +#PasswordAuthentication yes + +# Kerberos options +#KerberosAuthentication no +#KerberosGetAFSToken no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes + +X11Forwarding yes +X11DisplayOffset 10 +PrintMotd no +PrintLastLog yes +TCPKeepAlive yes +#UseLogin no + +#MaxStartups 10:30:60 +Banner /etc/issue.net + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +Subsystem sftp internal-sftp + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM yes +AllowUsers admin + +Match User sftpusers + ForceCommand internal-sftp + AllowTcpForwarding no + GatewayPorts no + X11Forwarding no diff --git a/data/templates/unattended/02periodic b/data/templates/unattended/02periodic new file mode 100644 index 00000000..c3ec9291 --- /dev/null +++ b/data/templates/unattended/02periodic @@ -0,0 +1,6 @@ +02periodic 50unattended-upgrades +root@65ba01d0c078:/usr/share/yunohost/yunohost-config/unattended# cat 02periodic +APT::Periodic::Enable "1"; +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; +APT::Periodic::Verbose "1"; diff --git a/data/templates/unattended/50unattended-upgrades b/data/templates/unattended/50unattended-upgrades new file mode 100644 index 00000000..49b600a3 --- /dev/null +++ b/data/templates/unattended/50unattended-upgrades @@ -0,0 +1,36 @@ +// Automatically upgrade packages from these (origin, archive) pairs +Unattended-Upgrade::Allowed-Origins { + "${distro_id} stable"; + "${distro_id} testing"; + "Depot-Debian testing"; + "${distro_id} ${distro_codename}-security"; + "${distro_id} ${distro_codename}-updates"; +// "${distro_id} ${distro_codename}-proposed-updates"; +}; + +// List of packages to not update +Unattended-Upgrade::Package-Blacklist { +// "vim"; +// "libc6"; +// "libc6-dev"; +// "libc6-i686"; +}; + +// Send email to this address for problems or packages upgrades +// If empty or unset then no email is sent, make sure that you +// have a working mail setup on your system. The package 'mailx' +// must be installed or anything that provides /usr/bin/mail. +//Unattended-Upgrade::Mail "root@localhost"; + +// Do automatic removal of new unused dependencies after the upgrade +// (equivalent to apt-get autoremove) +Unattended-Upgrade::Remove-Unused-Dependencies "true"; + +// Automatically reboot *WITHOUT CONFIRMATION* if a +// the file /var/run/reboot-required is found after the upgrade +Unattended-Upgrade::Automatic-Reboot "false"; + + +// Use apt bandwidth limit feature, this example limits the download +// speed to 70kb/sec +//Acquire::http::Dl-Limit "70"; diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 86a95933..3be221b2 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -23,14 +23,27 @@ Manage services """ +import os +import time import yaml import glob import subprocess import errno -import os.path +import shutil +import jinja2 +import difflib +import hashlib from moulinette.core import MoulinetteError +template_dir = os.getenv( + 'YUNOHOST_TEMPLATE_DIR', + '/usr/share/yunohost/templates' +) +conf_backup_dir = os.getenv( + 'YUNOHOST_CONF_BACKUP_DIR', + '/home/yunohost.backup/conffiles' +) def service_add(name, status=None, log=None, runlevel=None): """ @@ -257,9 +270,31 @@ def service_log(name, number=50): return result +def service_regenconf(auth, name=None, force=False, keep=False): + """ + Regenerate the configuration file(s) for a service and compare the result + with the existing configuration file. + Prints the differences between files if any. + + Keyword argument: + name -- Regenerate configuration for a specfic service + force -- Override the current configuration with the newly generated + one, even if it has been modified + keep -- Save the current configuration to avoid further notifications + + """ + if name is not None: + _regenerate_configuration_for(auth, name, force, keep) + + + #TODO: Raise error when force + keep + #TODO: Loop through all the services + #TODO: Win message with regenerated configurations + + def _run_service_command(action, service): """ - Run services management command (start, stop, enable, disable) + Run services management command (start, stop, enable, disable, restart, reload) Keyword argument: action -- Action to perform @@ -271,7 +306,7 @@ def _run_service_command(action, service): service)) cmd = None - if action in ['start', 'stop']: + if action in ['start', 'stop', 'restart', 'reload']: cmd = 'service %s %s' % (service, action) elif action in ['enable', 'disable']: arg = 'defaults' if action == 'enable' else 'remove' @@ -302,6 +337,7 @@ def _get_services(): else: return services + def _save_services(services): """ Save managed services to files @@ -314,6 +350,7 @@ def _save_services(services): with open('/etc/yunohost/services.yml', 'w') as f: yaml.safe_dump(services, f, default_flow_style=False) + def _tail(file, n, offset=None): """ Reads a n lines from f with an offset of offset lines. The return @@ -340,3 +377,268 @@ def _tail(file, n, offset=None): avg_line_length *= 1.3 except IOError: return [] + + +def _get_diff(string, filename): + """ + Show differences between a string and a file's content + + Keyword argument: + string -- The string + filename -- The file to compare with + + """ + try: + with open(filename, 'r') as f: + file_lines = f.readlines() + + string = string + '\n' + new_lines = string.splitlines(1) + return difflib.unified_diff(file_lines, new_lines) + except IOError: return [] + + +def _hash(filename): + """ + Calculate a MD5 hash of a file + + Keyword argument: + filename -- The file to hash + + """ + hasher = hashlib.md5() + try: + with open(filename, 'rb') as f: + buf = f.read() + hasher.update(buf) + + return hasher.hexdigest() + except IOError: + return 'no hash yet' + + +def _safe_remove(conf_file, service=None, force=False, keep=False): + """ + Check if the specific file has been modified before removing it. + Backup the file in /home/yunohost.backup + + Keyword argument: + conf_file -- The file to write + service -- Service name of the file to delete + force -- Force file deletion + keep -- Keep the current file and save its hash + + """ + deleted = False + + if not os.path.exists(conf_file): + try: + del services[service]['conffiles'][conf_file] + except KeyError: pass + return True + + services = _get_services() + + # Backup existing file + date = time.strftime("%Y%m%d.%H%M%S") + conf_backup_file = conf_backup_dir + conf_file +'-'+ date + process = subprocess.Popen( + ['install', '-D', conf_file, conf_backup_file] + ) + process.wait() + + # Retrieve hashes + if not 'conffiles' in services[service]: + services[service]['conffiles'] = {} + + if conf_file in services[service]['conffiles']: + previous_hash = services[service]['conffiles'][conf_file] + else: + previous_hash = 'no hash yet' + + current_hash = _hash(conf_file) + + # Handle conflicts + if force or previous_hash == current_hash: + os.remove(conf_file) + try: + del services[service]['conffiles'][conf_file] + except KeyError: pass + deleted = True + msignals.display(m18n.n('service_configuration_backup', conf_backup_file), + 'info') + elif keep: + services[service]['conffiles'][conf_file] = \ + previous_hash[0:32] + ', but keep ' + current_hash + msignals.display(m18n.n('service_configuration_backup', conf_backup_file), + 'info') + else: + services[service]['conffiles'][conf_file] = previous_hash + os.remove(conf_backup_file) + if os.isatty(1) and \ + (len(previous_hash) == 32 or previous_hash[-32:] != current_hash): + msignals.display( + m18n.n('service_configuration_changed', conf_file), + 'warning' + ) + + _save_services(services) + + return deleted + + +def _safe_write(conf_file, new_conf='', service=None, force=False, keep=False): + """ + Check if the specific file has been modified and display differences. + Stores the file hash in the services.yml file + + Keyword argument: + conf_file -- The file to write + new_conf -- String containing the new content + service -- Service name of the file to write + force -- Force file overriding + keep -- Keep the current file and save its hash + + """ + regenerated = False + services = _get_services() + + if os.path.exists(new_conf): + filename = new_conf + with open(filename, 'r') as f: + new_conf = ''.join(f.readlines()).rstrip() + + # Backup existing file + date = time.strftime("%Y%m%d.%H%M%S") + conf_backup_file = conf_backup_dir + conf_file +'-'+ date + if os.path.exists(conf_file): + process = subprocess.Popen( + ['install', '-D', conf_file, conf_backup_file] + ) + process.wait() + else: + msignals.display(m18n.n('service_add_configuration', conf_file), + 'info') + + # Retrieve hashes + if not 'conffiles' in services[service]: + services[service]['conffiles'] = {} + + if conf_file in services[service]['conffiles']: + previous_hash = services[service]['conffiles'][conf_file] + else: + previous_hash = 'no hash yet' + + current_hash = _hash(conf_file) + diff = list(_get_diff(new_conf, conf_file)) + + # Handle conflicts + if force or previous_hash == current_hash: + with open(conf_file, 'w') as f: f.write(new_conf) + regenerated = True + new_hash = _hash(conf_file) + elif keep: + new_hash = previous_hash[0:32] + ', but keep ' + current_hash + elif len(diff) == 0: + new_hash = _hash(conf_file) + else: + new_hash = previous_hash + if os.isatty(1) and \ + (len(previous_hash) == 32 or previous_hash[-32:] != current_hash): + msignals.display( + m18n.n('service_configuration_conflict', conf_file), + 'warning' + ) + print('\n' + conf_file) + for line in diff: + print(line.strip()) + print('') + + # Remove the backup file if the configuration has not changed + if new_hash == previous_hash: + os.remove(conf_backup_file) + elif os.path.exists(conf_backup_file): + msignals.display(m18n.n('service_configuration_backup', conf_backup_file), + 'info') + + services[service]['conffiles'][conf_file] = new_hash + _save_services(services) + + return regenerated + + +def _regenerate_configuration_for(auth, service, force=False, keep=False): + """ + Handle all the different services' configurations of YunoHost + + Keyword argument: + service -- Service name to take care of + force -- Force configuration overriding + keep -- Keep the current configuration and save its hash + + """ + from yunohost.domain import domain_list + + if service not in _get_services().keys() \ + or not os.path.isdir("%s/%s" % (template_dir, service)): + raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service)) + + # Set the service's template directory as Jinja Environment in order + # to ease the template loading + env = jinja2.Environment( + loader=jinja2.FileSystemLoader("%s/%s" % (template_dir, service)) + ) + + domains = domain_list(auth)['domains'] + + with open('/etc/yunohost/current_host', 'r') as f: + main_domain = f.readline().rstrip() + + if service == 'nginx': + + need_restart = False + + # Copy plain files + for filename in [ + 'ssowat.conf', + 'yunohost_admin.conf', + 'yunohost_admin.conf.inc', + 'yunohost_api.conf.inc', + 'yunohost_panel.conf.inc', + ]: + conf_file = '/etc/nginx/conf.d/%s' % filename + new_conf = '%s/%s/%s' % (template_dir, service, filename) + _safe_write(conf_file, new_conf, service, force, keep) + + # We need one file and one folder per virtualhost + for domain in domains: + conf_file = '/etc/nginx/conf.d/%s.conf' % domain + new_conf = env.get_template('server.conf.j2').render(domain=domain) + need_restart = _safe_write(conf_file, new_conf, service, force, keep) \ + or need_restart + try: + os.makedirs('/etc/nginx/conf.d/%s.d' % domain) + except OSError: pass + + # Copy yunohost_local.conf for the main domain + filename = 'yunohost_local.conf' + conf_file = '/etc/nginx/conf.d/%s.d/%s' % (main_domain, filename) + new_conf = '%s/%s/%s' % (template_dir, service, filename) + _safe_write(conf_file, new_conf, service, force, keep) + + # Backup and remove configuration for unexisting domains + for conf_file in os.listdir('/etc/nginx/conf.d/'): + if conf_file.endswith('.conf') and len(conf_file.split('.')) > 2 \ + and conf_file.replace('.conf', '') not in domains: + _safe_remove('/etc/nginx/conf.d/'+ conf_file, service, force, keep) + + # Restart Nginx + if need_restart: + _run_service_command('restart', service) + else: + _run_service_command('reload', service) + + msignals.display(m18n.n('service_configured', service), 'success') + + if service == 'postfix': + pass From d8dd81c64406dfbe1d75b3a94fec4c5c24610ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 13 Jul 2015 17:50:38 +0200 Subject: [PATCH 02/86] [fix] Display YunoHost packages versions (fix #11) --- bin/yunohost-api | 6 +++++- data/actionsmap/yunohost.yml | 8 +++++--- lib/yunohost/__init__.py | 38 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/bin/yunohost-api b/bin/yunohost-api index a15ba4f3..84f38c66 100755 --- a/bin/yunohost-api +++ b/bin/yunohost-api @@ -155,10 +155,14 @@ if __name__ == '__main__': _init_moulinette() from moulinette import (api, MoulinetteError) + from yunohost import get_versions try: # Run the server api(_retrieve_namespaces(), port=6787, - routes={('GET', '/installed'): is_installed}, + routes={ + ('GET', '/installed'): is_installed, + ('GET', '/version'): get_versions, + }, use_cache=USE_CACHE, use_websocket=USE_WEBSOCKET) except MoulinetteError as e: _die(e.strerror, m18n.g('error')) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 95180f0f..ee317f48 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -54,9 +54,11 @@ _global: arguments: -v: full: --version - help: Display moulinette version - action: version - version: moulinette %version% + help: Display YunoHost packages versions + action: callback + callback: + method: yunohost.get_versions + return: true ############################# # User # diff --git a/lib/yunohost/__init__.py b/lib/yunohost/__init__.py index e69de29b..97cd1f5f 100755 --- a/lib/yunohost/__init__.py +++ b/lib/yunohost/__init__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +""" YunoHost scripts for the moulinette """ + +""" License + + Copyright (C) 2015 YUNOHOST.ORG + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses + +""" + +## Packages versions + +def get_version(package): + from moulinette.utils import process + return process.check_output( + "dpkg-query -W -f='${{Version}}' {0}".format(package) + ).strip() + +def get_versions(*args, **kwargs): + from collections import OrderedDict + return OrderedDict([ + ('moulinette', get_version('moulinette')), + ('moulinette-yunohost', get_version('moulinette-yunohost')), + ('yunohost-admin', get_version('yunohost-admin')), + ]) From 65f2b5d324e512983290d76b7de3ddca415911b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 13 Jul 2015 17:51:17 +0200 Subject: [PATCH 03/86] [fix] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e4fc7d9e..a95de251 100644 --- a/.gitignore +++ b/.gitignore @@ -5,11 +5,11 @@ *.egg-info *.swp *.swo +*~ dist build eggs parts -bin cache var sdist From f352979b4cb9ab088c01952dfe7721062834ae5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 13 Jul 2015 22:46:38 +0200 Subject: [PATCH 04/86] [fix] Allow empty app arguments in app_install --- lib/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 73498ca9..5972b2d3 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -469,7 +469,7 @@ def app_install(auth, app, label=None, args=None): try: if args is None: args = '' - args_dict = dict(urlparse.parse_qsl(args)) + args_dict = dict(urlparse.parse_qsl(args, keep_blank_values=True)) except: args_dict = {} From a3b42427a724f919cdc0461b9fd96abdcb927f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Tue, 14 Jul 2015 22:14:57 +0200 Subject: [PATCH 05/86] [fix] Invalidate passwd at user creation/deletion (fix #70) --- lib/yunohost/user.py | 27 ++++++++++++++++++++++----- locales/en.json | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/lib/yunohost/user.py b/lib/yunohost/user.py index 15310346..897b53d3 100644 --- a/lib/yunohost/user.py +++ b/lib/yunohost/user.py @@ -24,7 +24,6 @@ Manage users """ import os -import sys import crypt import random import string @@ -35,6 +34,9 @@ import math import re from moulinette.core import MoulinetteError +from moulinette.utils.log import getActionLogger + +logger = getActionLogger('yunohost.user') def user_list(auth, fields=None, filter=None, limit=None, offset=None): @@ -141,7 +143,7 @@ def user_create(auth, username, firstname, lastname, mail, password, char_set = string.ascii_uppercase + string.digits salt = ''.join(random.sample(char_set,8)) salt = '$1$' + salt + '$' - pwd = '{CRYPT}' + crypt.crypt(str(password), salt) + user_pwd = '{CRYPT}' + crypt.crypt(str(password), salt) attr_dict = { 'objectClass' : ['mailAccount', 'inetOrgPerson', 'posixAccount'], 'givenName' : firstname, @@ -152,7 +154,7 @@ def user_create(auth, username, firstname, lastname, mail, password, 'mail' : mail, 'maildrop' : username, 'mailuserquota' : mailbox_quota, - 'userPassword' : pwd, + 'userPassword' : user_pwd, 'gidNumber' : uid, 'uidNumber' : uid, 'homeDirectory' : '/home/' + username, @@ -186,11 +188,23 @@ def user_create(auth, username, firstname, lastname, mail, password, if auth.add(rdn, attr_dict): + # Invalidate passwd to take user creation into account + subprocess.call(['nscd', '-i', 'passwd']) + # Update SFTP user group memberlist = auth.search(filter='cn=sftpusers', attrs=['memberUid'])[0]['memberUid'] memberlist.append(username) if auth.update('cn=sftpusers,ou=groups', { 'memberUid': memberlist }): - os.system("su - %s -c ''" % username) + try: + # Attempt to create user home folder + subprocess.check_call( + ['su', '-', username, '-c', "''"]) + except subprocess.CalledProcessError: + if not os.path.isdir('/home/{0}'.format(username)): + logger.exception('cannot create user home folder') + msignals.display( + m18n.n('user_home_creation_failed'), 'warning') + app_ssowatconf(auth) #TODO: Send a welcome mail to user msignals.display(m18n.n('user_created'), 'success') @@ -215,13 +229,16 @@ def user_delete(auth, username, purge=False): from yunohost.hook import hook_callback if auth.remove('uid=%s,ou=users' % username): + # Invalidate passwd to take user deletion into account + subprocess.call(['nscd', '-i', 'passwd']) + # Update SFTP user group memberlist = auth.search(filter='cn=sftpusers', attrs=['memberUid'])[0]['memberUid'] try: memberlist.remove(username) except: pass if auth.update('cn=sftpusers,ou=groups', { 'memberUid': memberlist }): if purge: - os.system('rm -rf /home/%s' % username) + subprocess.call(['rm', '-rf', '/home/{0}'.format(username)]) else: raise MoulinetteError(169, m18n.n('user_deletion_failed')) diff --git a/locales/en.json b/locales/en.json index c0d89a7b..64cfd7b4 100644 --- a/locales/en.json +++ b/locales/en.json @@ -169,6 +169,7 @@ "user_update_failed" : "Unable to update user", "user_updated" : "User successfully updated", "user_info_failed" : "Unable to retrieve user information", + "user_home_creation_failed" : "Unable to create user home folder", "admin_password" : "Administration password", "ask_firstname" : "First name", From 312dcd3bbe5eea1473b1531a7c913ef419e45c57 Mon Sep 17 00:00:00 2001 From: M5oul Date: Wed, 15 Jul 2015 15:28:09 +0200 Subject: [PATCH 06/86] Add AGPL license --- LICENSE | 661 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 661 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..dbbe3558 --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. From 45f5a9b2b981c123117bca431a7e07af825256be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Sat, 18 Jul 2015 16:41:58 +0200 Subject: [PATCH 07/86] [fix] Add minimum moulinette version in debian/control --- .gitignore | 3 +++ debian/control | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a95de251..726bba63 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ pip-log.txt # Mr Developer .mr.developer.cfg + +# moulinette lib +lib/yunohost/locales diff --git a/debian/control b/debian/control index a5f7bb63..6010b297 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Homepage: https://yunohost.org/ Package: moulinette-yunohost Architecture: all -Depends: moulinette, +Depends: moulinette (>= 2.2.1), python-psutil, python-requests, glances, From fd9e7f12fbc17c0385d6f19d5aee60e2d1a3d7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Sat, 18 Jul 2015 16:43:16 +0200 Subject: [PATCH 08/86] Update changelog for 2.2.3 release --- debian/changelog | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/debian/changelog b/debian/changelog index d264c81d..75e5da8a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +moulinette-yunohost (2.2.3) stable; urgency=low + + * [fix] Catch proper exception in backup_list (fix #65) + * [fix] Display YunoHost packages versions (fix #11) + * [fix] Allow empty app arguments in app_install + * [fix] Invalidate passwd at user creation/deletion (fix #70) + * [fix] Add minimum moulinette version in debian/control + + -- Jérôme Lebleu Sat, 18 Jul 2015 16:42:59 +0200 + moulinette-yunohost (2.2.2) stable; urgency=low * [fix] Avoid cd errors From cff745d174042ace423a94418651d7bca2c62713 Mon Sep 17 00:00:00 2001 From: ZeHiro Date: Tue, 21 Jul 2015 11:53:58 +0200 Subject: [PATCH 09/86] [fix] Fix skipped_urls for each domain and #68 Fixes https://github.com/YunoHost/moulinette-yunohost/issues/68 --- lib/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 5972b2d3..94f91f23 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -928,7 +928,7 @@ def app_ssowatconf(auth): redirected_regex.update(app_settings['redirected_regex']) for domain in domains: - skipped_urls.extend(['/yunohost/admin', '/yunohost/api']) + skipped_urls.extend([domain + '/yunohost/admin', domain + '/yunohost/api']) conf_dict = { 'portal_domain': main_domain, From bd37a080b817d2fef6c561818e9a760fee00ead0 Mon Sep 17 00:00:00 2001 From: nahoj Date: Sat, 25 Jul 2015 14:43:14 +0200 Subject: [PATCH 10/86] typo --- data/actionsmap/yunohost.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index ee317f48..660480a5 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -437,7 +437,7 @@ app: ### app_setting() setting: - action_help: Set ou get an app setting value + action_help: Set or get an app setting value api: GET /apps//settings arguments: app: From be620931646523029876c52c3f5e24c9213ce578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 27 Jul 2015 08:39:14 +0200 Subject: [PATCH 11/86] [fix] Correct logger object in backup_list (fix #75) --- lib/yunohost/backup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/backup.py b/lib/yunohost/backup.py index 4b072d11..7f98b118 100644 --- a/lib/yunohost/backup.py +++ b/lib/yunohost/backup.py @@ -299,7 +299,7 @@ def backup_list(): # Retrieve local archives archives = os.listdir(archives_path) except OSError as e: - logging.info("unable to iterate over local archives: %s", str(e)) + logger.info("unable to iterate over local archives: %s", str(e)) else: # Iterate over local archives for f in archives: From a2a7c720545190a855f1a2d5e2fbfd02d708d3f6 Mon Sep 17 00:00:00 2001 From: zamentur Date: Sun, 9 Aug 2015 15:00:13 +0200 Subject: [PATCH 12/86] [fix] 2nd installation of apps with a hooks directory --- lib/yunohost/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 94f91f23..421e017d 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -433,7 +433,7 @@ def app_install(auth, app, label=None, args=None): if 'hooks' in os.listdir(app_tmp_folder): for hook in os.listdir(app_tmp_folder +'/hooks'): #TODO: do it with sed ? - if file[:1] != '.': + if hook[:1] != '.': with open(app_tmp_folder +'/hooks/'+ hook, "r") as sources: lines = sources.readlines() with open(app_tmp_folder +'/hooks/'+ hook, "w") as sources: From 177f5f58f8dab52c7aabde1c374339c417ec03fa Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Thu, 3 Sep 2015 13:56:25 +0200 Subject: [PATCH 13/86] Add helper bash functions for apps developers --- data/apps/helpers | 7 +++++++ data/apps/helpers.d/password | 3 +++ debian/install | 1 + 3 files changed, 11 insertions(+) create mode 100644 data/apps/helpers create mode 100644 data/apps/helpers.d/password diff --git a/data/apps/helpers b/data/apps/helpers new file mode 100644 index 00000000..7473c96c --- /dev/null +++ b/data/apps/helpers @@ -0,0 +1,7 @@ +# -*- shell-script -*- + +# TODO : use --regex to validate against a namespace +for helper in $(run-parts --list /usr/share/yunohost/apps/helpers.d 2>/dev/null) ; do + [ -r $helper ] && . $helper || true +done + diff --git a/data/apps/helpers.d/password b/data/apps/helpers.d/password new file mode 100644 index 00000000..0087921c --- /dev/null +++ b/data/apps/helpers.d/password @@ -0,0 +1,3 @@ +ynh_password() { + echo $(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d '[A-Za-z0-9]' | sed -n 's/\(.\{24\}\).*/\1/p') +} diff --git a/debian/install b/debian/install index 405448e5..4c91fbd4 100644 --- a/debian/install +++ b/debian/install @@ -2,5 +2,6 @@ bin/* /usr/bin/ data/actionsmap/* /usr/share/moulinette/actionsmap/ data/hooks/* /usr/share/yunohost/hooks/ data/other/* /usr/share/yunohost/yunohost-config/moulinette/ +data/apps/* /usr/share/yunohost/apps/ lib/yunohost/*.py /usr/lib/moulinette/yunohost/ locales/* /usr/lib/moulinette/yunohost/locales/ From 258a9d6694e8f12bfe28e977bebaddfb88b7ad3b Mon Sep 17 00:00:00 2001 From: opi Date: Thu, 3 Sep 2015 14:24:50 +0200 Subject: [PATCH 14/86] [enh] Add ynh_user_exists helper. --- data/apps/helpers.d/user_exists | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 data/apps/helpers.d/user_exists diff --git a/data/apps/helpers.d/user_exists b/data/apps/helpers.d/user_exists new file mode 100644 index 00000000..662036f5 --- /dev/null +++ b/data/apps/helpers.d/user_exists @@ -0,0 +1,3 @@ +ynh_user_exists() { + sudo yunohost user list --json | grep -q "\"username\": \"${1}\"" +} \ No newline at end of file From 481fb00510175c86d827b4ed68ce4b48f2ac40b2 Mon Sep 17 00:00:00 2001 From: opi Date: Thu, 3 Sep 2015 14:36:27 +0200 Subject: [PATCH 15/86] [fix] Use one file for all user related helpers. --- data/apps/helpers.d/{user_exists => user} | 2 ++ 1 file changed, 2 insertions(+) rename data/apps/helpers.d/{user_exists => user} (76%) diff --git a/data/apps/helpers.d/user_exists b/data/apps/helpers.d/user similarity index 76% rename from data/apps/helpers.d/user_exists rename to data/apps/helpers.d/user index 662036f5..de9a2cbc 100644 --- a/data/apps/helpers.d/user_exists +++ b/data/apps/helpers.d/user @@ -1,3 +1,5 @@ + +# Check if a user exists ynh_user_exists() { sudo yunohost user list --json | grep -q "\"username\": \"${1}\"" } \ No newline at end of file From 559955a48b01db51e5f778b64044463196aafb72 Mon Sep 17 00:00:00 2001 From: Adrien Beudin Date: Thu, 3 Sep 2015 16:39:21 +0200 Subject: [PATCH 16/86] [fix] add netcat-openbsd packages in depends --- debian/control | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 6010b297..ee839136 100644 --- a/debian/control +++ b/debian/control @@ -18,6 +18,7 @@ Depends: moulinette (>= 2.2.1), bind9utils, python-apt, ca-certificates, - python-dnspython + python-dnspython, + netcat-openbsd Description: YunoHost Python scripts Python functions to manage a YunoHost instance From 545539cbf90825890106a7baf1a76c3a368594cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Tue, 8 Sep 2015 14:20:05 +0200 Subject: [PATCH 17/86] Update changelog for 2.3.0 release --- debian/changelog | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/debian/changelog b/debian/changelog index 75e5da8a..34a8b9eb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,32 @@ +moulinette-yunohost (2.3.0) testing; urgency=low + + [ M5oul ] + * Add AGPL license + + [ ZeHiro ] + * [fix] Fix skipped_urls for each domain and #68 + + [ nahoj ] + * typo + + [ Jérôme Lebleu ] + * [fix] Correct logger object in backup_list (fix #75) + + [ zamentur ] + * [fix] 2nd installation of apps with a hooks directory + + [ Julien Malik ] + * Add helper bash functions for apps developers + + [ opi ] + * [enh] Add ynh_user_exists helper. + * [fix] Use one file for all user related helpers. + + [ Adrien Beudin ] + * [fix] add netcat-openbsd packages in depends + + -- Jérôme Lebleu Tue, 08 Sep 2015 14:19:28 +0200 + moulinette-yunohost (2.2.3) stable; urgency=low * [fix] Catch proper exception in backup_list (fix #65) From 659b3126cc63140eb8286db945985cde408f4f6b Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:34:54 +0200 Subject: [PATCH 18/86] [fix] Indent postinst script uniformly --- debian/postinst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/debian/postinst b/debian/postinst index 2ad81579..279301c2 100644 --- a/debian/postinst +++ b/debian/postinst @@ -4,21 +4,21 @@ TMP=/usr/share/yunohost/yunohost-config/moulinette if [ ! -d /etc/yunohost ]; then - mkdir -p /etc/yunohost + mkdir -p /etc/yunohost fi # Allow users to access /media directory if [ ! -d /etc/skel/media ]; then - mkdir -p /media - ln -s /media /etc/skel/ + mkdir -p /media + ln -s /media /etc/skel/ fi #Firewall grep -q "UPNP:" /etc/yunohost/firewall.yml > /dev/null 2>&1 if [[ $? -eq 0 ]] || [ ! -f /etc/yunohost/firewall.yml ]; then - cp $TMP/firewall.yml /etc/yunohost/ + cp $TMP/firewall.yml /etc/yunohost/ fi # App fetchlist @@ -30,7 +30,7 @@ fi # Service list if [ ! -f /etc/yunohost/services.yml ]; then - cp $TMP/services.yml /etc/yunohost/ + cp $TMP/services.yml /etc/yunohost/ fi # Stop old API From 17e4872a9833c70c3aff657b777633e96930d6af Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:37:52 +0200 Subject: [PATCH 19/86] [enh] postinst : only respond to configure --- debian/postinst | 121 ++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 46 deletions(-) diff --git a/debian/postinst b/debian/postinst index 279301c2..564c9e1e 100644 --- a/debian/postinst +++ b/debian/postinst @@ -1,56 +1,85 @@ #!/bin/bash +#!/bin/sh +# postinst script for yunohost-config-metronome -TMP=/usr/share/yunohost/yunohost-config/moulinette +set -e -if [ ! -d /etc/yunohost ]; -then - mkdir -p /etc/yunohost -fi +do_configure() { + TMP=/usr/share/yunohost/yunohost-config/moulinette -# Allow users to access /media directory -if [ ! -d /etc/skel/media ]; -then - mkdir -p /media - ln -s /media /etc/skel/ -fi + if [ ! -d /etc/yunohost ]; + then + mkdir -p /etc/yunohost + fi -#Firewall -grep -q "UPNP:" /etc/yunohost/firewall.yml > /dev/null 2>&1 -if [[ $? -eq 0 ]] || [ ! -f /etc/yunohost/firewall.yml ]; -then - cp $TMP/firewall.yml /etc/yunohost/ -fi + # Allow users to access /media directory + if [ ! -d /etc/skel/media ]; + then + mkdir -p /media + ln -s /media /etc/skel/ + fi -# App fetchlist -if [ -f /etc/cron.d/yunohost-applist-yunohost ]; -then - sed -i "s/--no-ldap //g" /etc/cron.d/yunohost-applist-yunohost -fi + #Firewall + grep -q "UPNP:" /etc/yunohost/firewall.yml > /dev/null 2>&1 + if [[ $? -eq 0 ]] || [ ! -f /etc/yunohost/firewall.yml ]; + then + cp $TMP/firewall.yml /etc/yunohost/ + fi -# Service list -if [ ! -f /etc/yunohost/services.yml ]; -then - cp $TMP/services.yml /etc/yunohost/ -fi + # App fetchlist + if [ -f /etc/cron.d/yunohost-applist-yunohost ]; + then + sed -i "s/--no-ldap //g" /etc/cron.d/yunohost-applist-yunohost + fi -# Stop old API -ps aux | grep "yunohost.tac" | grep -qv grep -if [[ $? -eq 0 ]]; -then - killall twistd -fi + # Service list + if [ ! -f /etc/yunohost/services.yml ]; + then + cp $TMP/services.yml /etc/yunohost/ + fi -rm -rf /var/cache/moulinette/* -update-rc.d yunohost-api defaults -service yunohost-api restart + # Stop old API + ps aux | grep "yunohost.tac" | grep -qv grep + if [[ $? -eq 0 ]]; + then + killall twistd + fi -# Reload SSOwat conf if obsolete -if [ -f /etc/yunohost/installed ]; -then - yunohost firewall upnp | grep -qi "true" - if [[ $? -eq 0 ]]; - then - yunohost firewall upnp enable - fi - yunohost app ssowatconf -fi + rm -rf /var/cache/moulinette/* + update-rc.d yunohost-api defaults + service yunohost-api restart + + # Reload SSOwat conf if obsolete + if [ -f /etc/yunohost/installed ]; + then + yunohost firewall upnp | grep -qi "true" + if [[ $? -eq 0 ]]; + then + yunohost firewall upnp enable + fi + yunohost app ssowatconf + fi +} + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + +case "$1" in + configure) + do_configure + ;; + abort-upgrade|abort-remove|abort-deconfigure) + ;; + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac From 18984e646e9536bdad3fd6eb3040ee755655d0c2 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:39:29 +0200 Subject: [PATCH 20/86] [lintian] fix output-of-updaterc.d-not-redirected-to-dev-null yunohost-api postinst --- debian/postinst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/postinst b/debian/postinst index 564c9e1e..9b04e93e 100644 --- a/debian/postinst +++ b/debian/postinst @@ -46,7 +46,7 @@ do_configure() { fi rm -rf /var/cache/moulinette/* - update-rc.d yunohost-api defaults + update-rc.d yunohost-api defaults > /dev/null service yunohost-api restart # Reload SSOwat conf if obsolete From ef38929b71b89a0c5331972dbb4bb00903f29179 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:45:16 +0200 Subject: [PATCH 21/86] [lintian] fix postrm-contains-additional-updaterc.d-calls etc/init.d/yunohost-firewall --- debian/postinst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debian/postinst b/debian/postinst index 9b04e93e..9a537a19 100644 --- a/debian/postinst +++ b/debian/postinst @@ -49,6 +49,9 @@ do_configure() { update-rc.d yunohost-api defaults > /dev/null service yunohost-api restart + # Firewall + update-rc.d yunohost-firewall defaults > /dev/null + # Reload SSOwat conf if obsolete if [ -f /etc/yunohost/installed ]; then From d5e3b43ab9b94333c5da023357e5ddc2ed84e70d Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:54:58 +0200 Subject: [PATCH 22/86] [lintian] fix init.d-script-missing-lsb-description --- debian/yunohost-api.init | 1 + debian/yunohost-firewall.init | 1 + 2 files changed, 2 insertions(+) diff --git a/debian/yunohost-api.init b/debian/yunohost-api.init index 11c92b74..2bd0222b 100755 --- a/debian/yunohost-api.init +++ b/debian/yunohost-api.init @@ -6,6 +6,7 @@ # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start/stop YunoHost API +# Description: Start/stop YunoHost API ### END INIT INFO DAEMON=/usr/bin/yunohost-api diff --git a/debian/yunohost-firewall.init b/debian/yunohost-firewall.init index f16e1d6b..06bf2145 100755 --- a/debian/yunohost-firewall.init +++ b/debian/yunohost-firewall.init @@ -6,6 +6,7 @@ # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start/stop YunoHost firewall +# Description: Start/stop YunoHost firewall ### END INIT INFO DAEMON=/usr/bin/yunohost From a78435982c25aec366fe12a62418115e9a33c181 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:58:50 +0200 Subject: [PATCH 23/86] [lintian] fix init.d-script-does-not-implement-required-option etc/init.d/yunohost-api force-reload --- debian/yunohost-api.init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/yunohost-api.init b/debian/yunohost-api.init index 2bd0222b..3e75e159 100755 --- a/debian/yunohost-api.init +++ b/debian/yunohost-api.init @@ -41,7 +41,7 @@ case "$1" in kill `ps aux | grep 'yunohost-api' | grep -v grep | grep -v stop | awk '{print $2}'` > /dev/null 2>&1 log_end_msg 0 ;; - restart) + restart|force-reload) logger "YunoHost API: Restarting" log_daemon_msg "Restarting API: YunoHost" if [ -f /var/run/yunohost-api.pid ]; then @@ -67,7 +67,7 @@ case "$1" in ;; *) logger "YunoHost API: Invalid usage" - echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|status}" >&2 + echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|force-reload|status}" >&2 exit 1 ;; esac From 56841657978594dcb36d1313ec285c88824599df Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 18:59:49 +0200 Subject: [PATCH 24/86] [lintian] fix init.d-script-does-not-implement-required-option etc/init.d/yunohost-firewall force-reload --- debian/yunohost-firewall.init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/yunohost-firewall.init b/debian/yunohost-firewall.init index 06bf2145..fd144349 100755 --- a/debian/yunohost-firewall.init +++ b/debian/yunohost-firewall.init @@ -31,7 +31,7 @@ case "$1" in /usr/bin/yunohost firewall stop log_end_msg $? ;; - restart) + restart|force-reload) logger "YunoHost firewall: Restarting" log_daemon_msg "Restarting firewall: YunoHost" /usr/bin/yunohost firewall reload @@ -45,7 +45,7 @@ case "$1" in ;; *) logger "YunoHost API: Invalid usage" - echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|status}" >&2 + echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|force-reload|status}" >&2 exit 1 ;; esac From 2f92176fce499bdca1a6ddbb50f9e55a9e7082a6 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 19:07:47 +0200 Subject: [PATCH 25/86] [lintian] fix executable-not-elf-or-script usr/lib/moulinette/yunohost/__init__.py --- lib/yunohost/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 lib/yunohost/__init__.py diff --git a/lib/yunohost/__init__.py b/lib/yunohost/__init__.py old mode 100755 new mode 100644 From 940d5b588612498c304563692ad354f6e6fee240 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Wed, 9 Sep 2015 19:12:01 +0200 Subject: [PATCH 26/86] [lintian] fix script-not-executable for backup/restore hooks --- data/hooks/backup/05-system_ldap | 2 -- data/hooks/backup/08-system_ssh | 2 -- data/hooks/backup/11-system_mysql | 2 -- data/hooks/backup/14-system_ssowat | 2 -- data/hooks/backup/17-system_home | 2 -- data/hooks/backup/20-system_yunohost | 2 -- data/hooks/backup/23-system_mail | 2 -- data/hooks/backup/26-system_xmpp | 2 -- data/hooks/backup/29-system_nginx | 2 -- data/hooks/backup/32-system_cron | 2 -- data/hooks/restore/05-system_ldap | 2 -- data/hooks/restore/08-system_ssh | 2 -- data/hooks/restore/11-system_mysql | 2 -- data/hooks/restore/14-system_ssowat | 2 -- data/hooks/restore/17-system_home | 2 -- data/hooks/restore/20-system_yunohost | 2 -- data/hooks/restore/23-system_mail | 2 -- data/hooks/restore/26-system_xmpp | 2 -- data/hooks/restore/29-system_nginx | 2 -- data/hooks/restore/32-system_cron | 2 -- 20 files changed, 40 deletions(-) diff --git a/data/hooks/backup/05-system_ldap b/data/hooks/backup/05-system_ldap index 65c52fc7..9ef09b11 100644 --- a/data/hooks/backup/05-system_ldap +++ b/data/hooks/backup/05-system_ldap @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ldap" mkdir -p $backup_dir diff --git a/data/hooks/backup/08-system_ssh b/data/hooks/backup/08-system_ssh index 617eee0f..e5f2570e 100644 --- a/data/hooks/backup/08-system_ssh +++ b/data/hooks/backup/08-system_ssh @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ssh" mkdir -p $backup_dir diff --git a/data/hooks/backup/11-system_mysql b/data/hooks/backup/11-system_mysql index e5ff07c5..984d52a6 100644 --- a/data/hooks/backup/11-system_mysql +++ b/data/hooks/backup/11-system_mysql @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/mysql" mkdir -p $backup_dir diff --git a/data/hooks/backup/14-system_ssowat b/data/hooks/backup/14-system_ssowat index f4ec8c42..fbb78f19 100644 --- a/data/hooks/backup/14-system_ssowat +++ b/data/hooks/backup/14-system_ssowat @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ssowat" mkdir -p $backup_dir diff --git a/data/hooks/backup/17-system_home b/data/hooks/backup/17-system_home index 13414a75..b73b2dff 100644 --- a/data/hooks/backup/17-system_home +++ b/data/hooks/backup/17-system_home @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/home" mkdir -p $backup_dir diff --git a/data/hooks/backup/20-system_yunohost b/data/hooks/backup/20-system_yunohost index 22d556c6..e49b5289 100644 --- a/data/hooks/backup/20-system_yunohost +++ b/data/hooks/backup/20-system_yunohost @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/yunohost" mkdir -p $backup_dir diff --git a/data/hooks/backup/23-system_mail b/data/hooks/backup/23-system_mail index 2145c0bc..7fe210ce 100644 --- a/data/hooks/backup/23-system_mail +++ b/data/hooks/backup/23-system_mail @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/mail" sudo cp -a /var/mail/. $backup_dir diff --git a/data/hooks/backup/26-system_xmpp b/data/hooks/backup/26-system_xmpp index 836c7307..2b87644d 100644 --- a/data/hooks/backup/26-system_xmpp +++ b/data/hooks/backup/26-system_xmpp @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/xmpp" mkdir -p $backup_dir/{etc,var} diff --git a/data/hooks/backup/29-system_nginx b/data/hooks/backup/29-system_nginx index 6bbcae2c..97680912 100644 --- a/data/hooks/backup/29-system_nginx +++ b/data/hooks/backup/29-system_nginx @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/nginx" mkdir -p $backup_dir diff --git a/data/hooks/backup/32-system_cron b/data/hooks/backup/32-system_cron index b529b021..87a2a4f2 100644 --- a/data/hooks/backup/32-system_cron +++ b/data/hooks/backup/32-system_cron @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/cron" mkdir -p $backup_dir diff --git a/data/hooks/restore/05-system_ldap b/data/hooks/restore/05-system_ldap index 58ca04ea..f16225c3 100644 --- a/data/hooks/restore/05-system_ldap +++ b/data/hooks/restore/05-system_ldap @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ldap" if [ -z "$2" ]; then diff --git a/data/hooks/restore/08-system_ssh b/data/hooks/restore/08-system_ssh index 09aaf9c9..bfe729f3 100644 --- a/data/hooks/restore/08-system_ssh +++ b/data/hooks/restore/08-system_ssh @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ssh" sudo cp -a $backup_dir/. /etc/ssh diff --git a/data/hooks/restore/11-system_mysql b/data/hooks/restore/11-system_mysql index 28db5148..23293b15 100644 --- a/data/hooks/restore/11-system_mysql +++ b/data/hooks/restore/11-system_mysql @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/mysql" mysqlpwd=$(sudo cat /etc/yunohost/mysql) diff --git a/data/hooks/restore/14-system_ssowat b/data/hooks/restore/14-system_ssowat index df92fe10..15bae3c7 100644 --- a/data/hooks/restore/14-system_ssowat +++ b/data/hooks/restore/14-system_ssowat @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/ssowat" sudo cp -a $backup_dir/. /etc/ssowat diff --git a/data/hooks/restore/17-system_home b/data/hooks/restore/17-system_home index a90794ad..d005bed0 100644 --- a/data/hooks/restore/17-system_home +++ b/data/hooks/restore/17-system_home @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/home" sudo cp -a $backup_dir/. /home diff --git a/data/hooks/restore/20-system_yunohost b/data/hooks/restore/20-system_yunohost index 1bd33276..2ceb2ada 100644 --- a/data/hooks/restore/20-system_yunohost +++ b/data/hooks/restore/20-system_yunohost @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/yunohost" sudo cp -a $backup_dir/. /etc/yunohost diff --git a/data/hooks/restore/23-system_mail b/data/hooks/restore/23-system_mail index 39f6f933..ecef0ec1 100644 --- a/data/hooks/restore/23-system_mail +++ b/data/hooks/restore/23-system_mail @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/mail" sudo cp -a $backup_dir/. /var/mail diff --git a/data/hooks/restore/26-system_xmpp b/data/hooks/restore/26-system_xmpp index c1b4e360..70dc7e1c 100644 --- a/data/hooks/restore/26-system_xmpp +++ b/data/hooks/restore/26-system_xmpp @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/xmpp" sudo cp -a $backup_dir/etc/. /etc/metronome diff --git a/data/hooks/restore/29-system_nginx b/data/hooks/restore/29-system_nginx index 62810985..5ffaf5c1 100644 --- a/data/hooks/restore/29-system_nginx +++ b/data/hooks/restore/29-system_nginx @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/nginx" sudo cp -a $backup_dir/. /etc/nginx/conf.d diff --git a/data/hooks/restore/32-system_cron b/data/hooks/restore/32-system_cron index b1a53c3d..1e12d23b 100644 --- a/data/hooks/restore/32-system_cron +++ b/data/hooks/restore/32-system_cron @@ -1,5 +1,3 @@ -#!/bin/bash - backup_dir="$1/cron" sudo cp -a $backup_dir/. /etc/cron.d From 115df29afcedb8649430d15f3de31aaa74794033 Mon Sep 17 00:00:00 2001 From: Julien Malik Date: Thu, 10 Sep 2015 11:30:08 +0200 Subject: [PATCH 27/86] [fix] remove copy-pasted comments --- debian/postinst | 2 -- 1 file changed, 2 deletions(-) diff --git a/debian/postinst b/debian/postinst index 9a537a19..3106cfed 100644 --- a/debian/postinst +++ b/debian/postinst @@ -1,6 +1,4 @@ #!/bin/bash -#!/bin/sh -# postinst script for yunohost-config-metronome set -e From b2b1fc7d80cf73d47b18018446555b1cbb04f178 Mon Sep 17 00:00:00 2001 From: Le Kload Date: Tue, 22 Sep 2015 17:32:13 +0200 Subject: [PATCH 28/86] [fix] Ensure that arguments are passed to the hook as string --- lib/yunohost/hook.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/yunohost/hook.py b/lib/yunohost/hook.py index ccfd242b..635800e3 100644 --- a/lib/yunohost/hook.py +++ b/lib/yunohost/hook.py @@ -303,6 +303,7 @@ def hook_exec(file, args=None): if arg_list: # Concatenate arguments and escape them with double quotes to prevent # bash related issue if an argument is empty and is not the last + arg_list = [str(s) for s in arg_list] arg_str = '\\"{:s}\\"'.format('\\" \\"'.join(arg_list)) msignals.display(m18n.n('executing_script')) From 2b7b37d3e33afc84709b801494d3d88cf105ebc6 Mon Sep 17 00:00:00 2001 From: opi Date: Tue, 22 Sep 2015 19:53:59 +0200 Subject: [PATCH 29/86] [fix] Use SSL/TLS to fetch app list for christ's sake --- lib/yunohost/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 421e017d..d8b1b7b7 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -66,7 +66,7 @@ def app_fetchlist(url=None, name=None): Keyword argument: name -- Name of the list (default yunohost) - url -- URL of remote JSON list (default http://app.yunohost.org/list.json) + url -- URL of remote JSON list (default https://app.yunohost.org/list.json) """ # Create app path if not exists @@ -74,7 +74,7 @@ def app_fetchlist(url=None, name=None): except OSError: os.makedirs(repo_path) if url is None: - url = 'http://app.yunohost.org/list.json' + url = 'https://app.yunohost.org/list.json' name = 'yunohost' else: if name is None: From b45fcb1c986efe5754071a062cdca59a68e4c91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Sat, 26 Sep 2015 22:17:30 +0200 Subject: [PATCH 30/86] [fix] Replace bind9 by dnsmasq in services definition --- data/other/services.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/other/services.yml b/data/other/services.yml index 59fe141d..c183be54 100644 --- a/data/other/services.yml +++ b/data/other/services.yml @@ -4,7 +4,7 @@ nginx: avahi-daemon: status: service log: /var/log/daemon.log -bind9: +dnsmasq: status: service log: /var/log/daemon.log dovecot: From 0e8366adb532a74313ba212088841bd59f882a09 Mon Sep 17 00:00:00 2001 From: kload Date: Sat, 26 Sep 2015 22:28:49 +0200 Subject: [PATCH 31/86] [fix] IPv6 record in DynDNS --- data/actionsmap/yunohost.yml | 3 ++ lib/yunohost/dyndns.py | 70 +++++++++++++++++------------------- locales/en.json | 1 + locales/fr.json | 1 + 4 files changed, 37 insertions(+), 38 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 660480a5..93bc7642 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -1055,6 +1055,9 @@ dyndns: -i: full: --ip help: IP address to send + -6: + full: --ipv6 + help: IPv6 address to send ### dyndns_installcron() installcron: diff --git a/lib/yunohost/dyndns.py b/lib/yunohost/dyndns.py index 27650ad9..4504aaef 100644 --- a/lib/yunohost/dyndns.py +++ b/lib/yunohost/dyndns.py @@ -85,7 +85,7 @@ def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None dyndns_installcron() -def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=None): +def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=None, ipv6=None): """ Update IP on DynDNS platform @@ -94,12 +94,14 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non dyn_host -- Dynette DNS server to inform key -- Public DNS key ip -- IP address to send + ipv6 -- IPv6 address to send """ if domain is None: with open('/etc/yunohost/current_host', 'r') as f: domain = f.readline().rstrip() + # IPv4 if ip is None: try: new_ip = requests.get('http://ip.yunohost.org').text @@ -115,42 +117,22 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non old_ip = '0.0.0.0' # IPv6 - # TODO: Put global IPv6 in the DNS zone instead of ULA - new_ipv6 = None + if ipv6 is None: + try: + new_ipv6 = requests.get('http://ip6.yunohost.org').text + except ConnectionError: + msignals.display(m18n.n('no_ipv6_connectivity'), + 'warning') + else: + new_ipv6 = ipv6 + try: - with open('/etc/yunohost/ipv6') as f: + with open('/etc/yunohost/dyndns/old_ipv6', 'r') as f: old_ipv6 = f.readline().rstrip() except IOError: old_ipv6 = '0000:0000:0000:0000:0000:0000:0000:0000' - try: - # Get the interface - with open('/etc/yunohost/interface') as f: - interface = f.readline().rstrip() - # Get the ULA - with open('/etc/yunohost/ula') as f: - ula = f.readline().rstrip() - # Get the IPv6 address given by radvd and sanitize it - with open('/proc/net/if_inet6') as f: - plain_ula = '' - for hextet in ula.split(':')[0:3]: - if len(hextet) < 4: - hextet = '0000'+ hextet - hextet = hextet[-4:] - plain_ula = plain_ula + hextet - for line in f.readlines(): - if interface in line and plain_ula == line[0:12]: - new_ipv6 = ':'.join([line[0:32][i:i+4] for i in range(0, 32, 4)]) - with open('/etc/yunohost/ipv6', 'w+') as f: - f.write(new_ipv6) - break - except IOError: - pass - - if new_ipv6 is None: - new_ipv6 = '0000:0000:0000:0000:0000:0000:0000:0000' - - if old_ip != new_ip or old_ipv6 != new_ipv6 and new_ipv6 is not None: + if old_ip != new_ip or old_ipv6 != new_ipv6: host = domain.split('.')[1:] host = '.'.join(host) lines = [ @@ -161,22 +143,30 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non 'update delete %s. MX' % domain, 'update delete %s. TXT' % domain, 'update delete pubsub.%s. A' % domain, + 'update delete pubsub.%s. AAAA' % domain, 'update delete muc.%s. A' % domain, + 'update delete muc.%s. AAAA' % domain, 'update delete vjud.%s. A' % domain, + 'update delete vjud.%s. AAAA' % domain, 'update delete _xmpp-client._tcp.%s. SRV' % domain, 'update delete _xmpp-server._tcp.%s. SRV' % domain, 'update add %s. 1800 A %s' % (domain, new_ip), - 'update add %s. 1800 AAAA %s' % (domain, new_ipv6), 'update add %s. 14400 MX 5 %s.' % (domain, domain), 'update add %s. 14400 TXT "v=spf1 a mx -all"' % domain, 'update add pubsub.%s. 1800 A %s' % (domain, new_ip), - 'update add pubsub.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add muc.%s. 1800 A %s' % (domain, new_ip), - 'update add muc.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add vjud.%s. 1800 A %s' % (domain, new_ip), - 'update add vjud.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add _xmpp-client._tcp.%s. 14400 SRV 0 5 5222 %s.' % (domain, domain), - 'update add _xmpp-server._tcp.%s. 14400 SRV 0 5 5269 %s.' % (domain, domain), + 'update add _xmpp-server._tcp.%s. 14400 SRV 0 5 5269 %s.' % (domain, domain) + ] + if new_ipv6 is not None: + lines += [ + 'update add %s. 1800 AAAA %s' % (domain, new_ipv6), + 'update add pubsub.%s. 1800 AAAA %s' % (domain, new_ipv6), + 'update add muc.%s. 1800 AAAA %s' % (domain, new_ipv6), + 'update add vjud.%s. 1800 AAAA %s' % (domain, new_ipv6), + ] + lines += [ 'show', 'send' ] @@ -192,8 +182,12 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non msignals.display(m18n.n('dyndns_ip_updated'), 'success') with open('/etc/yunohost/dyndns/old_ip', 'w') as f: f.write(new_ip) + if new_ipv6 is not None: + with open('/etc/yunohost/dyndns/old_ipv6', 'w') as f: + f.write(new_ipv6) else: - os.system('rm /etc/yunohost/dyndns/old_ip > /dev/null 2>&1') + os.system('rm -f /etc/yunohost/dyndns/old_ip') + os.system('rm -f /etc/yunohost/dyndns/old_ipv6') raise MoulinetteError(errno.EPERM, m18n.n('dyndns_ip_update_failed')) diff --git a/locales/en.json b/locales/en.json index 64cfd7b4..2d5ff8dd 100644 --- a/locales/en.json +++ b/locales/en.json @@ -56,6 +56,7 @@ "domain_deletion_failed" : "Unable to delete domain", "domain_deleted" : "Domain successfully deleted", "no_internet_connection": "Server not connected to the Internet", + "no_ipv6_connectivity": "IPv6 connectivity is not available", "dyndns_key_generating" : "DNS key is being generated, it may take a while...", "dyndns_unavailable" : "Unavailable DynDNS subdomain", diff --git a/locales/fr.json b/locales/fr.json index 308d2ee7..d46c4c3e 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -53,6 +53,7 @@ "domain_deletion_failed": "Impossible de supprimer le domaine", "domain_deleted": "Domaine supprimé avec succès", "no_internet_connection": "Le serveur n'est pas connecté à Internet", + "no_ipv6_connectivity": "IPv6 n'est pas disponible", "dyndns_key_generating": "La clé DNS est en cours de génération, cela peut prendre du temps...", "dyndns_unavailable": "Sous-domaine DynDNS indisponible", "dyndns_registration_failed": "Impossible d'enregistrer le domaine DynDNS : {:s}", From e91f3797a558e84ecfc85c171d58ccfaf664eba4 Mon Sep 17 00:00:00 2001 From: Jocelyn Delande Date: Sun, 27 Sep 2015 01:14:42 +0200 Subject: [PATCH 32/86] [fix] fix UnboundLocalError on ConnectionError While connecting to ip6.yunohost.org, new_ip6 was not populated if exception. --- lib/yunohost/dyndns.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/yunohost/dyndns.py b/lib/yunohost/dyndns.py index 4504aaef..67b3db80 100644 --- a/lib/yunohost/dyndns.py +++ b/lib/yunohost/dyndns.py @@ -118,6 +118,7 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non # IPv6 if ipv6 is None: + new_ipv6 = None try: new_ipv6 = requests.get('http://ip6.yunohost.org').text except ConnectionError: From c586918a8ce822e0058d2bc383a3eab9ed673be5 Mon Sep 17 00:00:00 2001 From: Jocelyn Delande Date: Sun, 27 Sep 2015 01:16:56 +0200 Subject: [PATCH 33/86] [enh] Determine the public IPv6 locally Avoid depending on a remote service to fetch the globally routable IPv6 address. discussed in #89 --- debian/control | 3 ++- lib/yunohost/dyndns.py | 46 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/debian/control b/debian/control index ee839136..989cc26b 100644 --- a/debian/control +++ b/debian/control @@ -19,6 +19,7 @@ Depends: moulinette (>= 2.2.1), python-apt, ca-certificates, python-dnspython, - netcat-openbsd + netcat-openbsd, + iproute2 Description: YunoHost Python scripts Python functions to manage a YunoHost instance diff --git a/lib/yunohost/dyndns.py b/lib/yunohost/dyndns.py index 67b3db80..b4eb376d 100644 --- a/lib/yunohost/dyndns.py +++ b/lib/yunohost/dyndns.py @@ -26,14 +26,39 @@ import os import sys import requests +import re import json import glob import base64 import errno +import subprocess from moulinette.core import MoulinetteError +class IPRouteLine(object): + """ Utility class to parse an ip route output line + + The output of ip ro is variable and hard to parse completly, it would + require a real parser, not just a regexp, so do minimal parsing here... + + >>> a = IPRouteLine('2001:: from :: via fe80::c23f:fe:1e:cafe dev eth0 src 2000:de:beef:ca:0:fe:1e:cafe metric 0') + >>> a.src_addr + "2000:de:beef:ca:0:fe:1e:cafe" + """ + regexp = re.compile( + r'(?Punreachable)?.*src\s+(?P[0-9a-f:]+).*') + + def __init__(self, line): + self.m = self.regexp.match(line) + if not self.m: + raise ValueError("Not a valid ip route get line") + + # make regexp group available as object attributes + for k, v in self.m.groupdict().items(): + setattr(self, k, v) + + def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None): """ Subscribe to a DynDNS service @@ -120,10 +145,23 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non if ipv6 is None: new_ipv6 = None try: - new_ipv6 = requests.get('http://ip6.yunohost.org').text - except ConnectionError: - msignals.display(m18n.n('no_ipv6_connectivity'), - 'warning') + ip_route_out = subprocess.check_output( + ['ip', 'route', 'get', '2000::']).split('\n') + + if len(ip_route_out) > 0: + route = IPRouteLine(ip_route_out[0]) + if not route.unreachable: + new_ipv6 = route.src_addr + + except (OSError, ValueError) as e: + # Unlikely case "ip route" does not return status 0 + # or produces unexpected output + raise MoulinetteError(errno.EBADMSG, + "ip route cmd error : {}".format(e)) + + if new_ipv6 is None: + msignals.display(m18n.n('no_ipv6_connectivity'), 'warning') + else: new_ipv6 = ipv6 From 75b775b7a70863cc2a5c692d07906e4b96ce1ed1 Mon Sep 17 00:00:00 2001 From: kload Date: Sun, 27 Sep 2015 10:36:54 +0000 Subject: [PATCH 34/86] Update changelog for 2.3.1 release --- debian/changelog | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/debian/changelog b/debian/changelog index 34a8b9eb..c8d5a231 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,35 @@ +moulinette-yunohost (2.3.1) testing; urgency=low + + [ Julien Malik ] + * [fix] Indent postinst script uniformly + * [enh] postinst : only respond to configure + * [lintian] fix output-of-updaterc.d-not-redirected-to-dev-null yunohost-api postinst + * [lintian] fix postrm-contains-additional-updaterc.d-calls etc/init.d/yunohost-firewall + * [lintian] fix init.d-script-missing-lsb-description + * [lintian] fix init.d-script-does-not-implement-required-option etc/init.d/yunohost-api force-reload + * [lintian] fix init.d-script-does-not-implement-required-option etc/init.d/yunohost-firewall force-reload + * [lintian] fix executable-not-elf-or-script usr/lib/moulinette/yunohost/__init__.py + * [lintian] fix script-not-executable for backup/restore hooks + * [fix] remove copy-pasted comments + + [ Le Kload ] + * [fix] Ensure that arguments are passed to the hook as string + + [ opi ] + * [fix] Use SSL/TLS to fetch app list + + [ Jérôme Lebleu ] + * [fix] Replace bind9 by dnsmasq in services definition + + [ kload ] + * [fix] IPv6 record in DynDNS + + [ Jocelyn Delande ] + * [fix] fix UnboundLocalError on ConnectionError + * [enh] Determine the public IPv6 locally + + -- kload Sun, 27 Sep 2015 10:36:34 +0000 + moulinette-yunohost (2.3.0) testing; urgency=low [ M5oul ] From 442e578f0e5cf5f1676bd23c68ab35d80666420f Mon Sep 17 00:00:00 2001 From: Le Kload Date: Mon, 28 Sep 2015 18:55:14 +0200 Subject: [PATCH 35/86] [fix] Compatibility for Jessie and Wheezy --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 989cc26b..561083c2 100644 --- a/debian/control +++ b/debian/control @@ -20,6 +20,6 @@ Depends: moulinette (>= 2.2.1), ca-certificates, python-dnspython, netcat-openbsd, - iproute2 + iproute Description: YunoHost Python scripts Python functions to manage a YunoHost instance From b6c77c9e43a5e6fbc7e3326b2c09eaa7bc7114ad Mon Sep 17 00:00:00 2001 From: kload Date: Mon, 28 Sep 2015 16:53:36 +0000 Subject: [PATCH 36/86] [enh] Regenerate configuration via hook scripts --- data/actionsmap/yunohost.yml | 43 +++++++++-- data/hooks/conf_regen/15-nginx | 57 +++++++++++++++ lib/yunohost/domain.py | 10 ++- lib/yunohost/hook.py | 10 +++ lib/yunohost/service.py | 127 +++++++-------------------------- 5 files changed, 140 insertions(+), 107 deletions(-) create mode 100644 data/hooks/conf_regen/15-nginx diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 93bc7642..a037b789 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -243,6 +243,10 @@ domain: authenticate: all authenticator: ldap-anonymous arguments: + -r: + full: --raw + help: Return domains as a bash-usable list instead of JSON + action: store_true -f: full: --filter help: LDAP filter used to search @@ -879,18 +883,47 @@ service: Prints the differences between files if any. api: PUT /services/regenconf arguments: - -n: - full: --name + -s: + full: --service help: Regenerate configuration for a specfic service -f: full: --force help: Override the current configuration with the newly generated one, even if it has been modified action: store_true - -k: - full: --keep - help: Save the current configuration to avoid further notifications + + ### service_safecopy() + safecopy: + action_help: > + Check if the specific file has been modified and display differences. + Stores the file hash in the services.yml file + api: PUT /services/safecopy + arguments: + service: + help: Service name attached to the conf file + new_conf_file: + help: Path to the desired conf file + conf_file: + help: Path to the targeted conf file + -f: + full: --force + help: Override the current configuration with the newly generated one, even if it has been modified action: store_true + ### service_saferemove() + saferemove: + action_help: > + Check if the specific file has been modified before removing it. + Backup the file in /home/yunohost.backup + api: PUT /services/safecopy + arguments: + service: + help: Service name attached to the conf file + conf_file: + help: Path to the targeted conf file + -f: + full: --force + help: Force file deletion + action: store_true ############################# # Firewall # diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx new file mode 100644 index 00000000..2cc5eae3 --- /dev/null +++ b/data/hooks/conf_regen/15-nginx @@ -0,0 +1,57 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if $force; then + sudo yunohost service safecopy \ + -s nginx \ + --force \ + $1 $2 + else + sudo yunohost service safecopy \ + -s nginx \ + $1 $2 + fi +} + +cd /usr/share/yunohost/templates/nginx + +# Copy plain single configuration files +$files="ssowat.conf +yunohost_admin.conf +yunohost_admin.conf.inc +yunohost_api.conf.inc +yunohost_panel.conf.inc" + +for file in files; do + safe_copy $file /etc/nginx/conf.d/$file +done + + +# Copy 'yunohost.local' to the main domain conf directory +main_domain=$(sudo yunohost tools maindomain) +safe_copy yunohost_local.conf \ + /etc/nginx/conf.d/$main_domain.d/yunohost_local.conf + + +need_restart=0 + +# Copy a configuration file for each YunoHost domain +for domain in $(sudo yunohost domain list --raw); do + sudo mkdir /etc/nginx/conf.d/$domain.d + cat server.conf.sed \ + | sed "s/{{ domain }}/$domain/g" \ + | sudo tee $domain.conf + if $(safe_copy $domain.conf /etc/nginx/conf.d/$domain.conf); then + need_restart=1 + fi +done + +# Restart if need be +if $need_restart; then + service nginx restart +else + service nginx reload +fi diff --git a/lib/yunohost/domain.py b/lib/yunohost/domain.py index d8880554..2463e977 100644 --- a/lib/yunohost/domain.py +++ b/lib/yunohost/domain.py @@ -36,11 +36,12 @@ from urllib import urlopen from moulinette.core import MoulinetteError -def domain_list(auth, filter=None, limit=None, offset=None): +def domain_list(auth, raw=False, filter=None, limit=None, offset=None): """ List domains Keyword argument: + raw -- Return domains as a bash-usable list instead of JSON filter -- LDAP filter used to search offset -- Starting number for domain fetching limit -- Maximum number of domain fetched @@ -61,7 +62,12 @@ def domain_list(auth, filter=None, limit=None, offset=None): if len(result) > offset and limit > 0: for domain in result[offset:offset+limit]: result_list.append(domain['virtualdomain'][0]) - return { 'domains': result_list } + + if raw: + for domain in result_list: + print domain + else: + return { 'domains': result_list } def domain_add(auth, domain, dyndns=False): diff --git a/lib/yunohost/hook.py b/lib/yunohost/hook.py index 635800e3..4c4bd063 100644 --- a/lib/yunohost/hook.py +++ b/lib/yunohost/hook.py @@ -185,6 +185,16 @@ def hook_callback(action, hooks=[], args=None): else: hooks_names = hook_list(action, list_by='name', show_info=True)['hooks'] + + # Add similar hooks to the list + # For example: Having a 16-postfix hook in the list will execute a + # xx-postfix_dkim as well + for n in hooks: + for key in hooks.keys(): + if key.startswith("%s_" % n) \ + and n not in hooks: + hooks.append(n) + # Iterate over given hooks names list for n in hooks: try: diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 3be221b2..26ac27d6 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -30,7 +30,6 @@ import glob import subprocess import errno import shutil -import jinja2 import difflib import hashlib @@ -270,26 +269,35 @@ def service_log(name, number=50): return result -def service_regenconf(auth, name=None, force=False, keep=False): +def service_regenconf(service=None, force=False): """ Regenerate the configuration file(s) for a service and compare the result with the existing configuration file. Prints the differences between files if any. Keyword argument: - name -- Regenerate configuration for a specfic service + service -- Regenerate configuration for a specfic service force -- Override the current configuration with the newly generated one, even if it has been modified - keep -- Save the current configuration to avoid further notifications """ - if name is not None: - _regenerate_configuration_for(auth, name, force, keep) - - - #TODO: Raise error when force + keep - #TODO: Loop through all the services - #TODO: Win message with regenerated configurations + if force: + arg_force = 1 + else: + arg_force = 0 + + if service is None: + # Regen ALL THE CONFIGURATIONS + hook_callback('conf_regen', args=[arg_force]) + + msignals.display(m18n.n('services_configured'), 'success') + else: + if service not in _get_services().keys(): + raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service)) + + hook_callback('conf_regen', [service] , args=[arg_force]) + + msignals.display(m18n.n('service_configured', service), 'success') def _run_service_command(action, service): @@ -417,16 +425,15 @@ def _hash(filename): return 'no hash yet' -def _safe_remove(conf_file, service=None, force=False, keep=False): +def service_saferemove(service, conf_file, force=False): """ Check if the specific file has been modified before removing it. Backup the file in /home/yunohost.backup Keyword argument: - conf_file -- The file to write service -- Service name of the file to delete + conf_file -- The file to write force -- Force file deletion - keep -- Keep the current file and save its hash """ deleted = False @@ -487,24 +494,23 @@ def _safe_remove(conf_file, service=None, force=False, keep=False): return deleted -def _safe_write(conf_file, new_conf='', service=None, force=False, keep=False): +def service_safecopy(service, new_conf_file, conf_file, force=False): """ Check if the specific file has been modified and display differences. Stores the file hash in the services.yml file Keyword argument: - conf_file -- The file to write - new_conf -- String containing the new content - service -- Service name of the file to write + service -- Service name attached to the conf file + new_conf_file -- Path to the desired conf file + conf_file -- Path to the targeted conf file force -- Force file overriding - keep -- Keep the current file and save its hash """ regenerated = False services = _get_services() - if os.path.exists(new_conf): - filename = new_conf + if os.path.exists(new_conf_file): + filename = new_conf_file with open(filename, 'r') as f: new_conf = ''.join(f.readlines()).rstrip() @@ -537,8 +543,6 @@ def _safe_write(conf_file, new_conf='', service=None, force=False, keep=False): with open(conf_file, 'w') as f: f.write(new_conf) regenerated = True new_hash = _hash(conf_file) - elif keep: - new_hash = previous_hash[0:32] + ', but keep ' + current_hash elif len(diff) == 0: new_hash = _hash(conf_file) else: @@ -565,80 +569,3 @@ def _safe_write(conf_file, new_conf='', service=None, force=False, keep=False): _save_services(services) return regenerated - - -def _regenerate_configuration_for(auth, service, force=False, keep=False): - """ - Handle all the different services' configurations of YunoHost - - Keyword argument: - service -- Service name to take care of - force -- Force configuration overriding - keep -- Keep the current configuration and save its hash - - """ - from yunohost.domain import domain_list - - if service not in _get_services().keys() \ - or not os.path.isdir("%s/%s" % (template_dir, service)): - raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service)) - - # Set the service's template directory as Jinja Environment in order - # to ease the template loading - env = jinja2.Environment( - loader=jinja2.FileSystemLoader("%s/%s" % (template_dir, service)) - ) - - domains = domain_list(auth)['domains'] - - with open('/etc/yunohost/current_host', 'r') as f: - main_domain = f.readline().rstrip() - - if service == 'nginx': - - need_restart = False - - # Copy plain files - for filename in [ - 'ssowat.conf', - 'yunohost_admin.conf', - 'yunohost_admin.conf.inc', - 'yunohost_api.conf.inc', - 'yunohost_panel.conf.inc', - ]: - conf_file = '/etc/nginx/conf.d/%s' % filename - new_conf = '%s/%s/%s' % (template_dir, service, filename) - _safe_write(conf_file, new_conf, service, force, keep) - - # We need one file and one folder per virtualhost - for domain in domains: - conf_file = '/etc/nginx/conf.d/%s.conf' % domain - new_conf = env.get_template('server.conf.j2').render(domain=domain) - need_restart = _safe_write(conf_file, new_conf, service, force, keep) \ - or need_restart - try: - os.makedirs('/etc/nginx/conf.d/%s.d' % domain) - except OSError: pass - - # Copy yunohost_local.conf for the main domain - filename = 'yunohost_local.conf' - conf_file = '/etc/nginx/conf.d/%s.d/%s' % (main_domain, filename) - new_conf = '%s/%s/%s' % (template_dir, service, filename) - _safe_write(conf_file, new_conf, service, force, keep) - - # Backup and remove configuration for unexisting domains - for conf_file in os.listdir('/etc/nginx/conf.d/'): - if conf_file.endswith('.conf') and len(conf_file.split('.')) > 2 \ - and conf_file.replace('.conf', '') not in domains: - _safe_remove('/etc/nginx/conf.d/'+ conf_file, service, force, keep) - - # Restart Nginx - if need_restart: - _run_service_command('restart', service) - else: - _run_service_command('reload', service) - - msignals.display(m18n.n('service_configured', service), 'success') - - if service == 'postfix': - pass From cfc661e61258dfd68b78c9d0ea38f096fa06fb18 Mon Sep 17 00:00:00 2001 From: kload Date: Mon, 28 Sep 2015 16:31:19 -0400 Subject: [PATCH 37/86] [fix] Make Nginx configuration generation to work --- data/actionsmap/yunohost.yml | 16 ++++++++--- data/hooks/conf_regen/.15-nginx.swn | Bin 0 -> 12288 bytes data/hooks/conf_regen/15-nginx | 26 +++++++++--------- .../nginx/{server.conf.j2 => server.conf.sed} | 0 lib/yunohost/service.py | 6 ++-- 5 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 data/hooks/conf_regen/.15-nginx.swn rename data/templates/nginx/{server.conf.j2 => server.conf.sed} (100%) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index a037b789..371ecf26 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -882,6 +882,8 @@ service: with the existing configuration file. Prints the differences between files if any. api: PUT /services/regenconf + configuration: + lock: false arguments: -s: full: --service @@ -898,12 +900,15 @@ service: Stores the file hash in the services.yml file api: PUT /services/safecopy arguments: - service: - help: Service name attached to the conf file new_conf_file: help: Path to the desired conf file conf_file: help: Path to the targeted conf file + -s: + full: --service + help: Service name attached to the conf file + extra: + required: True -f: full: --force help: Override the current configuration with the newly generated one, even if it has been modified @@ -916,10 +921,13 @@ service: Backup the file in /home/yunohost.backup api: PUT /services/safecopy arguments: - service: - help: Service name attached to the conf file conf_file: help: Path to the targeted conf file + -s: + full: --service + help: Service name attached to the conf file + extra: + required: True -f: full: --force help: Force file deletion diff --git a/data/hooks/conf_regen/.15-nginx.swn b/data/hooks/conf_regen/.15-nginx.swn new file mode 100644 index 0000000000000000000000000000000000000000..72192c866529e1ce91ae554265e8b90c14a73f9c GIT binary patch literal 12288 zcmeI2-)me&6vt1+2eplgKcEzZ)6HrV0B0l&(h~nQM2nwwa7De#EN53=o-ejYx3%)65;KNO3=AN1P%$X%iW_#oM z)mQlW-m`@AFwu86@4vpYaxdM!LR2{yV)e2Tj1RecZ*N(@4`M(yb@NGSO$a92n_D+_ zKBz(mt;Wvnc$GUl98_jxtlE4ov!l|!yDYA>ivcmP#K1fZvr8-V%*D-(*mJdWo*#YW zjU_KhvltKqVn7Ut0Wly3#DEwO1OF!jVRni>#DeZ=7WG2&JoT4n^Q%0>fEW-1Vn7Ut z0Wly3#DEwO17bi7h=Kp00bLM1{Qx+P$>ab3?f3uRA0oN~eg;2+AHcWZOYjl!K!aDo zOW+A`ANb=zqTj%;;1}=>_!@i+Zh&1d09U~VP~a@MvqJO}xD9TB&%puM0#AV_K^Hs@ z9s}Q>A^HsL0}U>LbKoni;|uU9xCuT1H^23E5CdZ1 zE(V4rF^ZoTj=ibgDRaZ=ekxaH;_!#GnRs*eE!BIsZnnqW!cBE)d+|aoD-&{+CYvtU z_6oJwyw3eTcdk`))8ValI&mQ8_v`frV~z!+)EHYa&5l?5`&qyJ4IP>Hv5NJ7BqBKJ49*YLgO~H7l_-IN$CS;S*3T^FQX1hUyLd= zM+xOBfZ`(=0e-tOCw$2;9~x84Aw3o?Kz~HJh&>} z%RbDaqbYThg%c7Z)+gPmLzEqV@JT4OgAZofntGYN(&n9`20bh5T}JgnZ82?fF?K(x zp3*4&j`wa?hgx8>f3rzkn=kDM`}X&(^h9~VYVIrL$GS3yd!d4v;$7TNuX7(?DN{Z! z93|%NCU-BUYEC8d&8e<4G}ax@wf5{smFc9_9S=``6DC7~<@M36YtleX-Zy>z=`oz!JSF$h4zI2AKE<8PO}~pY_6CQ;Fs+_f+oe_8+K=f^uGH2& literal 0 HcmV?d00001 diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 2cc5eae3..0eaa4ea1 100644 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -4,11 +4,11 @@ set -e force=$1 function safe_copy () { - if $force; then + if [ $force ]; then sudo yunohost service safecopy \ -s nginx \ - --force \ - $1 $2 + $1 $2 \ + --force else sudo yunohost service safecopy \ -s nginx \ @@ -19,39 +19,39 @@ function safe_copy () { cd /usr/share/yunohost/templates/nginx # Copy plain single configuration files -$files="ssowat.conf +files="ssowat.conf yunohost_admin.conf yunohost_admin.conf.inc yunohost_api.conf.inc yunohost_panel.conf.inc" -for file in files; do +for file in $files; do safe_copy $file /etc/nginx/conf.d/$file done # Copy 'yunohost.local' to the main domain conf directory -main_domain=$(sudo yunohost tools maindomain) +main_domain=$(cat /etc/yunohost/current_host) safe_copy yunohost_local.conf \ /etc/nginx/conf.d/$main_domain.d/yunohost_local.conf -need_restart=0 +need_restart=1 # Copy a configuration file for each YunoHost domain for domain in $(sudo yunohost domain list --raw); do - sudo mkdir /etc/nginx/conf.d/$domain.d + sudo mkdir -p /etc/nginx/conf.d/$domain.d cat server.conf.sed \ | sed "s/{{ domain }}/$domain/g" \ | sudo tee $domain.conf - if $(safe_copy $domain.conf /etc/nginx/conf.d/$domain.conf); then - need_restart=1 + if [[ $(safe_copy $domain.conf /etc/nginx/conf.d/$domain.conf) == "True" ]]; then + need_restart=0 fi done # Restart if need be -if $need_restart; then - service nginx restart +if [ $need_restart ]; then + sudo service nginx restart else - service nginx reload + sudo service nginx reload fi diff --git a/data/templates/nginx/server.conf.j2 b/data/templates/nginx/server.conf.sed similarity index 100% rename from data/templates/nginx/server.conf.j2 rename to data/templates/nginx/server.conf.sed diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 26ac27d6..5bed72e9 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -281,10 +281,12 @@ def service_regenconf(service=None, force=False): one, even if it has been modified """ + from yunohost.hook import hook_callback + if force: - arg_force = 1 - else: arg_force = 0 + else: + arg_force = 1 if service is None: # Regen ALL THE CONFIGURATIONS From b9f9a3f1057b044d11c8e33240a365533e701fe7 Mon Sep 17 00:00:00 2001 From: kload Date: Mon, 28 Sep 2015 19:47:43 -0400 Subject: [PATCH 38/86] [enh] Add slapd conf regen hook --- data/hooks/conf_regen/.15-nginx.swn | Bin 12288 -> 0 bytes data/hooks/conf_regen/06-slapd | 40 ++++++++++++++++++++++++++++ data/templates/slapd/ldap.conf | 18 +++++++++++++ lib/yunohost/service.py | 9 ++++--- 4 files changed, 63 insertions(+), 4 deletions(-) delete mode 100644 data/hooks/conf_regen/.15-nginx.swn create mode 100644 data/hooks/conf_regen/06-slapd create mode 100644 data/templates/slapd/ldap.conf diff --git a/data/hooks/conf_regen/.15-nginx.swn b/data/hooks/conf_regen/.15-nginx.swn deleted file mode 100644 index 72192c866529e1ce91ae554265e8b90c14a73f9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2-)me&6vt1+2eplgKcEzZ)6HrV0B0l&(h~nQM2nwwa7De#EN53=o-ejYx3%)65;KNO3=AN1P%$X%iW_#oM z)mQlW-m`@AFwu86@4vpYaxdM!LR2{yV)e2Tj1RecZ*N(@4`M(yb@NGSO$a92n_D+_ zKBz(mt;Wvnc$GUl98_jxtlE4ov!l|!yDYA>ivcmP#K1fZvr8-V%*D-(*mJdWo*#YW zjU_KhvltKqVn7Ut0Wly3#DEwO1OF!jVRni>#DeZ=7WG2&JoT4n^Q%0>fEW-1Vn7Ut z0Wly3#DEwO17bi7h=Kp00bLM1{Qx+P$>ab3?f3uRA0oN~eg;2+AHcWZOYjl!K!aDo zOW+A`ANb=zqTj%;;1}=>_!@i+Zh&1d09U~VP~a@MvqJO}xD9TB&%puM0#AV_K^Hs@ z9s}Q>A^HsL0}U>LbKoni;|uU9xCuT1H^23E5CdZ1 zE(V4rF^ZoTj=ibgDRaZ=ekxaH;_!#GnRs*eE!BIsZnnqW!cBE)d+|aoD-&{+CYvtU z_6oJwyw3eTcdk`))8ValI&mQ8_v`frV~z!+)EHYa&5l?5`&qyJ4IP>Hv5NJ7BqBKJ49*YLgO~H7l_-IN$CS;S*3T^FQX1hUyLd= zM+xOBfZ`(=0e-tOCw$2;9~x84Aw3o?Kz~HJh&>} z%RbDaqbYThg%c7Z)+gPmLzEqV@JT4OgAZofntGYN(&n9`20bh5T}JgnZ82?fF?K(x zp3*4&j`wa?hgx8>f3rzkn=kDM`}X&(^h9~VYVIrL$GS3yd!d4v;$7TNuX7(?DN{Z! z93|%NCU-BUYEC8d&8e<4G}ax@wf5{smFc9_9S=``6DC7~<@M36YtleX-Zy>z=`oz!JSF$h4zI2AKE<8PO}~pY_6CQ;Fs+_f+oe_8+K=f^uGH2& diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd new file mode 100644 index 00000000..05fd8172 --- /dev/null +++ b/data/hooks/conf_regen/06-slapd @@ -0,0 +1,40 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [ $force ]; then + sudo yunohost service safecopy \ + -s slapd \ + $1 $2 \ + --force + else + sudo yunohost service safecopy \ + -s slapd \ + $1 $2 + fi +} + +cd /usr/share/yunohost/templates/slapd + +safe_copy mailserver.schema /etc/ldap/schema/mailserver.schema +safe_copy ldap.conf /etc/ldap/ldap.conf +safe_copy slapd.default /etc/default/slapd + +# Compatibility: change from HDB to MDB on Jessie +version=$(sed 's/\..*//' /etc/debian_version) +if [[ "$version" == '8' ]]; then + sudo sed -i "s/ hdb/ mdb/g" slapd.conf +fi + +safe_copy slapd.conf /etc/ldap/slapd.conf +sudo chown root:openldap /etc/ldap/slapd.conf +sudo rm -Rf /etc/ldap/slapd.d +sudo mkdir /etc/ldap/slapd.d +sudo chown -R openldap:openldap /etc/ldap/schema/ +sudo chown -R openldap:openldap /etc/ldap/slapd.d/ + +sudo slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ + +sudo service slapd force-reload diff --git a/data/templates/slapd/ldap.conf b/data/templates/slapd/ldap.conf new file mode 100644 index 00000000..bfd86e8a --- /dev/null +++ b/data/templates/slapd/ldap.conf @@ -0,0 +1,18 @@ +# +# LDAP Defaults +# + +# See ldap.conf(5) for details +# This file should be world readable but not world writable. + +#BASE dc=example,dc=com +#URI ldap://ldap.example.com ldap://ldap-master.example.com:666 + +#SIZELIMIT 12 +#TIMELIMIT 15 +#DEREF never + +# TLS certificates (needed for GnuTLS) +TLS_CACERT /etc/ssl/certs/ca-certificates.crt + +sudoers_base ou=sudo,dc=yunohost,dc=org diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 5bed72e9..9fd264f6 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -511,10 +511,11 @@ def service_safecopy(service, new_conf_file, conf_file, force=False): regenerated = False services = _get_services() - if os.path.exists(new_conf_file): - filename = new_conf_file - with open(filename, 'r') as f: - new_conf = ''.join(f.readlines()).rstrip() + if not os.path.exists(new_conf_file): + raise MoulinetteError(errno.EIO, m18n.n('no_such_conf_file', new_conf_file)) + + with open(new_conf_file, 'r') as f: + new_conf = ''.join(f.readlines()).rstrip() # Backup existing file date = time.strftime("%Y%m%d.%H%M%S") From 2a812e0aec1b0bd0ca7c746e4de422a1cb53ac36 Mon Sep 17 00:00:00 2001 From: kload Date: Tue, 29 Sep 2015 06:15:01 -0400 Subject: [PATCH 39/86] [enh] Add nslcd conf regen script --- data/hooks/conf_regen/06-slapd | 2 + data/hooks/conf_regen/09-nslcd | 27 +++++++++ data/templates/nslcd/nslcd.conf | 1 - data/templates/ssh/sshd_config-ipv4 | 93 ----------------------------- lib/yunohost/service.py | 4 ++ 5 files changed, 33 insertions(+), 94 deletions(-) create mode 100644 data/hooks/conf_regen/09-nslcd delete mode 100644 data/templates/ssh/sshd_config-ipv4 diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd index 05fd8172..ccc418dd 100644 --- a/data/hooks/conf_regen/06-slapd +++ b/data/hooks/conf_regen/06-slapd @@ -26,6 +26,8 @@ safe_copy slapd.default /etc/default/slapd version=$(sed 's/\..*//' /etc/debian_version) if [[ "$version" == '8' ]]; then sudo sed -i "s/ hdb/ mdb/g" slapd.conf + sudo sed -i "s/back_hdb/back_mdb/g" slapd.conf + sudo sed -i "s/dbconfig set_/#dbconfig set_/g" slapd.conf fi safe_copy slapd.conf /etc/ldap/slapd.conf diff --git a/data/hooks/conf_regen/09-nslcd b/data/hooks/conf_regen/09-nslcd new file mode 100644 index 00000000..9356eec4 --- /dev/null +++ b/data/hooks/conf_regen/09-nslcd @@ -0,0 +1,27 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [ $force ]; then + sudo yunohost service safecopy \ + -s nslcd \ + $1 $2 \ + --force + else + sudo yunohost service safecopy \ + -s nslcd \ + $1 $2 + fi +} + +cd /usr/share/yunohost/templates/nslcd + +safe_copy nslcd.conf /etc/nslcd.conf + +# Fix: Add a blank line at the end of the file +# to avoid nscld restart failure +echo -e "\n" | sudo tee -a /etc/nslcd.conf + +sudo service nslcd restart diff --git a/data/templates/nslcd/nslcd.conf b/data/templates/nslcd/nslcd.conf index b2daf777..9774613f 100644 --- a/data/templates/nslcd/nslcd.conf +++ b/data/templates/nslcd/nslcd.conf @@ -1,4 +1,3 @@ -root@65ba01d0c078:/usr/share/yunohost/yunohost-config/slapd# cat /etc/nslcd.conf # /etc/nslcd.conf # nslcd configuration file. See nslcd.conf(5) # for details. diff --git a/data/templates/ssh/sshd_config-ipv4 b/data/templates/ssh/sshd_config-ipv4 deleted file mode 100644 index 1545b607..00000000 --- a/data/templates/ssh/sshd_config-ipv4 +++ /dev/null @@ -1,93 +0,0 @@ -# Package generated configuration file -# See the sshd_config(5) manpage for details - -# What ports, IPs and protocols we listen for -Port 22 -# Use these options to restrict which interfaces/protocols sshd will bind to -#ListenAddress :: -ListenAddress 0.0.0.0 -Protocol 2 -# HostKeys for protocol version 2 -HostKey /etc/ssh/ssh_host_rsa_key -HostKey /etc/ssh/ssh_host_dsa_key -#Privilege Separation is turned on for security -UsePrivilegeSeparation yes - -# Lifetime and size of ephemeral version 1 server key -KeyRegenerationInterval 3600 -ServerKeyBits 768 - -# Logging -SyslogFacility AUTH -LogLevel INFO - -# Authentication: -LoginGraceTime 120 -PermitRootLogin no -StrictModes yes - -RSAAuthentication yes -PubkeyAuthentication yes -#AuthorizedKeysFile %h/.ssh/authorized_keys - -# Don't read the user's ~/.rhosts and ~/.shosts files -IgnoreRhosts yes -# For this to work you will also need host keys in /etc/ssh_known_hosts -RhostsRSAAuthentication no -# similar for protocol version 2 -HostbasedAuthentication no -# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication -#IgnoreUserKnownHosts yes - -# To enable empty passwords, change to yes (NOT RECOMMENDED) -PermitEmptyPasswords no - -# Change to yes to enable challenge-response passwords (beware issues with -# some PAM modules and threads) -ChallengeResponseAuthentication no - -# Change to no to disable tunnelled clear text passwords -#PasswordAuthentication yes - -# Kerberos options -#KerberosAuthentication no -#KerberosGetAFSToken no -#KerberosOrLocalPasswd yes -#KerberosTicketCleanup yes - -# GSSAPI options -#GSSAPIAuthentication no -#GSSAPICleanupCredentials yes - -X11Forwarding yes -X11DisplayOffset 10 -PrintMotd no -PrintLastLog yes -TCPKeepAlive yes -#UseLogin no - -#MaxStartups 10:30:60 -Banner /etc/issue.net - -# Allow client to pass locale environment variables -AcceptEnv LANG LC_* - -Subsystem sftp internal-sftp - -# Set this to 'yes' to enable PAM authentication, account processing, -# and session processing. If this is enabled, PAM authentication will -# be allowed through the ChallengeResponseAuthentication and -# PasswordAuthentication. Depending on your PAM configuration, -# PAM authentication via ChallengeResponseAuthentication may bypass -# the setting of "PermitRootLogin without-password". -# If you just want the PAM account and session checks to run without -# PAM authentication, then enable this but set PasswordAuthentication -# and ChallengeResponseAuthentication to 'no'. -UsePAM yes -AllowUsers admin - -Match User sftpusers - ForceCommand internal-sftp - AllowTcpForwarding no - GatewayPorts no - X11Forwarding no diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 9fd264f6..52fe6ad3 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -529,6 +529,10 @@ def service_safecopy(service, new_conf_file, conf_file, force=False): msignals.display(m18n.n('service_add_configuration', conf_file), 'info') + # Add the service if it does not exist + if service not in services.keys(): + services[service] = {} + # Retrieve hashes if not 'conffiles' in services[service]: services[service]['conffiles'] = {} From 1ca528f6ce431965aed317fa7819d5a0697c55cc Mon Sep 17 00:00:00 2001 From: kload Date: Tue, 29 Sep 2015 06:49:06 -0400 Subject: [PATCH 40/86] [fix] Properly calculate diff --- data/hooks/conf_regen/03-ssh | 31 +++++++++++++++++++++++++++++++ data/hooks/conf_regen/06-slapd | 2 +- data/hooks/conf_regen/09-nslcd | 2 +- data/hooks/conf_regen/15-nginx | 8 ++++---- lib/yunohost/service.py | 11 +++-------- 5 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 data/hooks/conf_regen/03-ssh diff --git a/data/hooks/conf_regen/03-ssh b/data/hooks/conf_regen/03-ssh new file mode 100644 index 00000000..2481bd31 --- /dev/null +++ b/data/hooks/conf_regen/03-ssh @@ -0,0 +1,31 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [ $force ]; then + sudo yunohost service safecopy \ + -s ssh \ + $1 $2 \ + --force + else + sudo yunohost service safecopy \ + -s ssh \ + $1 $2 + fi +} + +cd /usr/share/yunohost/templates/ssh + +# Only overwrite SSH configuration on an ISO installation +if [ ! -f /etc/yunohost/from_script ]; then + + # Do not listen to IPv6 if unavailable + if [ ! -f /proc/net/if_inet6 ]; then + sudo sed -i "s/ListenAddress ::/#ListenAddress ::/g" sshd_config + fi + safe_copy sshd_config /etc/ssh/sshd_config + + sudo service ssh restart +fi diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd index ccc418dd..24e76d98 100644 --- a/data/hooks/conf_regen/06-slapd +++ b/data/hooks/conf_regen/06-slapd @@ -4,7 +4,7 @@ set -e force=$1 function safe_copy () { - if [ $force ]; then + if [[ "$force" == "True" ]]; then sudo yunohost service safecopy \ -s slapd \ $1 $2 \ diff --git a/data/hooks/conf_regen/09-nslcd b/data/hooks/conf_regen/09-nslcd index 9356eec4..da09e6ac 100644 --- a/data/hooks/conf_regen/09-nslcd +++ b/data/hooks/conf_regen/09-nslcd @@ -4,7 +4,7 @@ set -e force=$1 function safe_copy () { - if [ $force ]; then + if [[ "$force" == "True" ]]; then sudo yunohost service safecopy \ -s nslcd \ $1 $2 \ diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 0eaa4ea1..37f976ed 100644 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -4,7 +4,7 @@ set -e force=$1 function safe_copy () { - if [ $force ]; then + if [[ "$force" == "True" ]]; then sudo yunohost service safecopy \ -s nginx \ $1 $2 \ @@ -36,7 +36,7 @@ safe_copy yunohost_local.conf \ /etc/nginx/conf.d/$main_domain.d/yunohost_local.conf -need_restart=1 +need_restart=False # Copy a configuration file for each YunoHost domain for domain in $(sudo yunohost domain list --raw); do @@ -45,12 +45,12 @@ for domain in $(sudo yunohost domain list --raw); do | sed "s/{{ domain }}/$domain/g" \ | sudo tee $domain.conf if [[ $(safe_copy $domain.conf /etc/nginx/conf.d/$domain.conf) == "True" ]]; then - need_restart=0 + need_restart=True fi done # Restart if need be -if [ $need_restart ]; then +if [[ "$need_restart" == "True" ]]; then sudo service nginx restart else sudo service nginx reload diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 52fe6ad3..8f3a7693 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -283,14 +283,9 @@ def service_regenconf(service=None, force=False): """ from yunohost.hook import hook_callback - if force: - arg_force = 0 - else: - arg_force = 1 - if service is None: # Regen ALL THE CONFIGURATIONS - hook_callback('conf_regen', args=[arg_force]) + hook_callback('conf_regen', args=[force]) msignals.display(m18n.n('services_configured'), 'success') else: @@ -402,7 +397,6 @@ def _get_diff(string, filename): with open(filename, 'r') as f: file_lines = f.readlines() - string = string + '\n' new_lines = string.splitlines(1) return difflib.unified_diff(file_lines, new_lines) except IOError: return [] @@ -548,8 +542,9 @@ def service_safecopy(service, new_conf_file, conf_file, force=False): # Handle conflicts if force or previous_hash == current_hash: with open(conf_file, 'w') as f: f.write(new_conf) - regenerated = True new_hash = _hash(conf_file) + if current_hash != new_hash: + regenerated = True elif len(diff) == 0: new_hash = _hash(conf_file) else: From 380487314205c79f71caa9111200987c9b2b345f Mon Sep 17 00:00:00 2001 From: kload Date: Tue, 29 Sep 2015 07:26:53 -0400 Subject: [PATCH 41/86] [fix] Regen conf for specific service --- lib/yunohost/hook.py | 11 ++++++----- lib/yunohost/service.py | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/yunohost/hook.py b/lib/yunohost/hook.py index 4c4bd063..9aeb3564 100644 --- a/lib/yunohost/hook.py +++ b/lib/yunohost/hook.py @@ -189,14 +189,15 @@ def hook_callback(action, hooks=[], args=None): # Add similar hooks to the list # For example: Having a 16-postfix hook in the list will execute a # xx-postfix_dkim as well + all_hooks = [] for n in hooks: - for key in hooks.keys(): - if key.startswith("%s_" % n) \ - and n not in hooks: - hooks.append(n) + for key in hooks_names.keys(): + if key == n or key.startswith("%s_" % n) \ + and key not in all_hooks: + all_hooks.append(key) # Iterate over given hooks names list - for n in hooks: + for n in all_hooks: try: hl = hooks_names[n] except KeyError: diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 8f3a7693..ceac04ad 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -292,7 +292,7 @@ def service_regenconf(service=None, force=False): if service not in _get_services().keys(): raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service)) - hook_callback('conf_regen', [service] , args=[arg_force]) + hook_callback('conf_regen', [service] , args=[force]) msignals.display(m18n.n('service_configured', service), 'success') From ec63f336cfaa06ba83a58ab421d3d4f6f7f5b05b Mon Sep 17 00:00:00 2001 From: kload Date: Tue, 29 Sep 2015 08:52:34 -0400 Subject: [PATCH 42/86] [enh] Metronome regen script --- data/hooks/conf_regen/12-metronome | 59 ++++++ data/templates/metronome/domain.cfg.lua.sed | 15 ++ data/templates/metronome/metronome.cfg.lua | 131 ------------ .../templates/metronome/metronome.cfg.lua.sed | 193 ++++++++++++++++++ data/templates/metronome/metronome.init | 134 ++++++------ data/templates/metronome/metronome.logrotate | 18 +- .../metronome/modules/mod_legacyauth.lua | 116 +++++------ lib/yunohost/service.py | 10 +- 8 files changed, 416 insertions(+), 260 deletions(-) create mode 100644 data/hooks/conf_regen/12-metronome create mode 100644 data/templates/metronome/domain.cfg.lua.sed delete mode 100644 data/templates/metronome/metronome.cfg.lua create mode 100644 data/templates/metronome/metronome.cfg.lua.sed diff --git a/data/hooks/conf_regen/12-metronome b/data/hooks/conf_regen/12-metronome new file mode 100644 index 00000000..c0824c33 --- /dev/null +++ b/data/hooks/conf_regen/12-metronome @@ -0,0 +1,59 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s metronome \ + $1 $2 \ + --force + else + sudo yunohost service safecopy \ + -s metronome \ + $1 $2 + fi +} + +cd /usr/share/yunohost/templates/metronome + +# Copy additional modules +files="ldap.lib.lua +mod_auth_ldap2.lua +mod_legacyauth.lua +mod_storage_ldap.lua +vcard.lib.lua" + +for file in $files; do + safe_copy modules/$file /usr/lib/metronome/modules/$file +done + +# Copy configuration files +main_domain=$(cat /etc/yunohost/current_host) +cat metronome.cfg.lua.sed \ + | sed "s/{{ main_domain }}/$main_domain/g" \ + | sudo tee metronome.cfg.lua +safe_copy metronome.cfg.lua /etc/metronome/metronome.cfg.lua +safe_copy metronome.init /etc/init.d/metronome +safe_copy metronome.logrotate /etc/logrotate.d/metronome + +need_restart=False +sudo mkdir -p /etc/metronome/conf.d + +# Copy a configuration file for each YunoHost domain +for domain in $(sudo yunohost domain list --raw); do + cat domain.cfg.lua.sed \ + | sed "s/{{ domain }}/$domain/g" \ + | sudo tee $domain.cfg.lua + if [[ $(safe_copy $domain.cfg.lua /etc/metronome/conf.d/$domain.cfg.lua) == "True" ]]; then + need_restart=True + fi +done + +# Restart if need be +if [[ "$need_restart" == "True" ]]; then + sudo service metronome restart +else + sudo service metronome reload +fi diff --git a/data/templates/metronome/domain.cfg.lua.sed b/data/templates/metronome/domain.cfg.lua.sed new file mode 100644 index 00000000..2c7fd748 --- /dev/null +++ b/data/templates/metronome/domain.cfg.lua.sed @@ -0,0 +1,15 @@ +VirtualHost "{{ domain }}" + ssl = { + key = "/etc/yunohost/certs/{{ domain }}/key.pem"; + certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem"; + } + authentication = "ldap2" + ldap = { + hostname = "localhost", + user = { + basedn = "ou=users,dc=yunohost,dc=org", + filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }}))", + usernamefield = "mail", + namefield = "cn", + }, + } diff --git a/data/templates/metronome/metronome.cfg.lua b/data/templates/metronome/metronome.cfg.lua deleted file mode 100644 index 240dc4e2..00000000 --- a/data/templates/metronome/metronome.cfg.lua +++ /dev/null @@ -1,131 +0,0 @@ --- ** Metronome's config file example ** --- --- The format is exactly equal to Prosody's: --- --- Lists are written { "like", "this", "one" } --- Lists can also be of { 1, 2, 3 } numbers, etc. --- Either commas, or semi-colons; may be used as seperators. --- --- A table is a list of values, except each value has a name. An --- example would be: --- --- ssl = { key = "keyfile.key", certificate = "certificate.crt" } --- --- Tip: You can check that the syntax of this file is correct when you have finished --- by running: luac -p metronome.cfg.lua --- If there are any errors, it will let you know what and where they are, otherwise it --- will keep quiet. - --- Global settings go in this section - --- This is the list of modules Metronome will load on startup. --- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too. - -pidfile = "/var/run/metronome/metronome.pid" - -log = { - info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging - error = "/var/log/metronome/metronome.err"; - "*syslog"; -} - -modules_enabled = { - - -- Generally required - "roster"; -- Allow users to have a roster. Recommended ;) - "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. - "tls"; -- Add support for secure TLS on c2s/s2s connections - "dialback"; -- s2s dialback support - "disco"; -- Service discovery - - -- Not essential, but recommended - "private"; -- Private XML storage (for room bookmarks, etc.) - "vcard"; -- Allow users to set vCards - "privacy"; -- Support privacy lists - --"compression"; -- Stream compression (Debian: requires lua-zlib module to work) - - -- Nice to have - "legacyauth"; -- Legacy authentication. Only used by some old clients and bots. - "version"; -- Replies to server version requests - "uptime"; -- Report how long server has been running - "time"; -- Let others know the time here on this server - "ping"; -- Replies to XMPP pings with pongs - "pep"; -- Enables users to publish their mood, activity, playing music and more - "register"; -- Allow users to register on this server using a client and change passwords - "adhoc"; -- Support for "ad-hoc commands" that can be executed with an XMPP client - - -- Admin interfaces - "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands - "admin_telnet"; -- Opens telnet console interface on localhost port 5582 - - -- Other specific functionality - "bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" - --"httpserver"; -- Serve static files from a directory over HTTP - --"groups"; -- Shared roster support - --"announce"; -- Send announcement to all online users - --"welcome"; -- Welcome users who register accounts - --"watchregistrations"; -- Alert admins of registrations - --"motd"; -- Send a message to users when they log in - "mam"; -- Nice archive management - -- Debian: do not remove this module, or you lose syslog - -- support - "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. -}; - --- Discovery items -disco_items = { - { "muc.yunohost.org" }, - { "vjud.yunohost.org" }, - { "pubsub.yunohost.org" } -}; - -use_ipv6 = true -c2s_require_encryption = false -s2s_secure = true - --- HTTP ports -http_ports = { 5290 } -https_ports = { 5291 } - --- BOSH configuration (mod_bosh) -bosh_max_inactivity = 30 -consider_bosh_secure = true -cross_domain_bosh = true - -anonymous_login = false -allow_registration = false - -storage = "ldap" - -Component "localhost" "http" - modules_enabled = { "bosh" } - -Component "muc.yunohost.org" "muc" - name = "YunoHost Chatrooms" - - modules_enabled = { - "muc_limits"; - "muc_log"; - "muc_log_http"; - } - - muc_event_rate = 0.5 - muc_burst_factor = 10 - - muc_log_http = { - http_port = 5290; - show_join = true; - show_status = false; - theme = "metronome"; - } - -Component "pubsub.yunohost.org" "pubsub" - name = "YunoHost Publish/Subscribe" - unrestricted_node_creation = true - -Component "vjud.yunohost.org" "vjud" - ud_disco_name = "Jappix User Directory" - -Include "conf.d/*.cfg.lua" - - diff --git a/data/templates/metronome/metronome.cfg.lua.sed b/data/templates/metronome/metronome.cfg.lua.sed new file mode 100644 index 00000000..9fce19a8 --- /dev/null +++ b/data/templates/metronome/metronome.cfg.lua.sed @@ -0,0 +1,193 @@ +-- ** Metronome's config file example ** +-- +-- The format is exactly equal to Prosody's: +-- +-- Lists are written { "like", "this", "one" } +-- Lists can also be of { 1, 2, 3 } numbers, etc. +-- Either commas, or semi-colons; may be used as seperators. +-- +-- A table is a list of values, except each value has a name. An +-- example would be: +-- +-- ssl = { key = "keyfile.key", certificate = "certificate.crt" } +-- +-- Tip: You can check that the syntax of this file is correct when you have finished +-- by running: luac -p metronome.cfg.lua +-- If there are any errors, it will let you know what and where they are, otherwise it +-- will keep quiet. + +---------- Server-wide settings ---------- +-- Settings in this section apply to the whole server and are the default settings +-- for any virtual hosts + +-- Server PID +pidfile = "/var/run/metronome/metronome.pid" + +-- HTTP server +http_ports = { 5290 } +http_interfaces = { "127.0.0.1", "::1" } + +--https_ports = { 5291 } +--https_interfaces = { "127.0.0.1", "::1" } + +-- Enable IPv6 +use_ipv6 = true + +-- This is the list of modules Metronome will load on startup. +-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too. +modules_enabled = { + + -- Generally required + "roster"; -- Allow users to have a roster. Recommended ;) + "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. + "tls"; -- Add support for secure TLS on c2s/s2s connections + "dialback"; -- s2s dialback support + "disco"; -- Service discovery + --"discoitems"; -- Service discovery items + --"extdisco"; -- External Service Discovery + + -- Not essential, but recommended + "private"; -- Private XML storage (for room bookmarks, etc.) + "vcard"; -- Allow users to set vCards + "privacy"; -- Support privacy lists + + -- These are commented by default as they have a performance impact + --"compression"; -- Stream compression (Debian: requires lua-zlib module to work) + + -- Nice to have + "version"; -- Replies to server version requests + "uptime"; -- Report how long server has been running + "time"; -- Let others know the time here on this server + "ping"; -- Replies to XMPP pings with pongs + "pep"; -- Enables users to publish their mood, activity, playing music and more + "message_carbons"; -- Allow clients to keep in sync with messages send on other resources + "register"; -- Allow users to register on this server using a client and change passwords + "adhoc"; -- Support for "ad-hoc commands" that can be executed with an XMPP client + + -- Admin interfaces + "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands + "admin_telnet"; -- Opens telnet console interface on localhost port 5582 + + -- HTTP modules + "bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" + --"websockets"; -- Enable WebSocket clients + --"http_files"; -- Serve static files from a directory over HTTP + + -- Other specific functionality +-- "bidi"; -- Bidirectional Streams for S2S connections +-- "stream_management"; -- Stream Management support + --"groups"; -- Shared roster support + --"announce"; -- Send announcement to all online users + --"welcome"; -- Welcome users who register accounts + --"watchregistrations"; -- Alert admins of registrations + --"motd"; -- Send a message to users when they log in + "mam"; -- Nice archive management + --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots. + "offline"; -- Store offline messages + "c2s"; -- Handle client connections + "s2s"; -- Handle server-to-server connections + + -- Debian: do not remove this module, or you lose syslog + -- support + "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. +}; + +-- Discovery items +disco_items = { + { "muc.{{ main_domain }}" }, + { "pubsub.{{ main_domain }}" }, + { "vjud.{{ main_domain }}" } +}; + +-- BOSH configuration (mod_bosh) +bosh_max_inactivity = 30 +consider_bosh_secure = true +cross_domain_bosh = true + +-- Disable account creation by default, for security +allow_registration = false + +-- SSL/TLS configuration +ssl = { + options = { + "no_sslv2", + "no_sslv3", + "no_ticket", + "no_compression", + "cipher_server_preference" + }; +} + +-- Force clients to use encrypted connections? This option will +-- prevent clients from authenticating unless they are using encryption. +c2s_require_encryption = true + +-- Force servers to use encrypted connections? This option will +-- prevent servers from connecting unless they are using encryption. +s2s_require_encryption = true + +-- Allow servers to use an unauthenticated encryption channel +s2s_allow_encryption = true + +allow_unencrypted_plain_auth = false; + +s2s_secure = true +s2s_secure_auth = false + +--anonymous_login = false + +-- Use LDAP storage backend for all stores +storage = "ldap" + +-- Logging configuration +log = { + info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging + error = "/var/log/metronome/metronome.err"; + -- "*syslog"; -- Uncomment this for logging to syslog + -- "*console"; -- Log to the console, useful for debugging with daemonize=false +} + + +------ Components ------ +-- You can specify components to add hosts that provide special services, +-- like multi-user conferences, and transports. + +---Set up a local BOSH service +Component "localhost" "http" + modules_enabled = { "bosh" } + +---Set up a MUC (multi-user chat) room server +Component "muc.{{ main_domain }}" "muc" + name = "YunoHost Chatrooms" + + modules_enabled = { + "muc_limits"; + "muc_log"; + "muc_log_http"; + } + + muc_event_rate = 0.5 + muc_burst_factor = 10 + + muc_log_http_config = { + url_base = "logs"; + theme = "metronome"; + } + +---Set up a PubSub server +Component "pubsub.{{ main_domain }}" "pubsub" + name = "YunoHost Publish/Subscribe" + + unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server) + +---Set up a VJUD service +Component "vjud.{{ main_domain }}" "vjud" + ud_disco_name = "Jappix User Directory" + + +----------- Virtual hosts ----------- +-- You need to add a VirtualHost entry for each domain you wish Metronome to serve. +-- Settings under each VirtualHost entry apply *only* to that host. + +Include "conf.d/*.cfg.lua" + diff --git a/data/templates/metronome/metronome.init b/data/templates/metronome/metronome.init index 62c04846..5f6f2ed4 100644 --- a/data/templates/metronome/metronome.init +++ b/data/templates/metronome/metronome.init @@ -2,8 +2,8 @@ ### BEGIN INIT INFO # Provides: metronome -# Required-Start: $network $local_fs $remote_fs -# Required-Stop: $remote_fs +# Required-Start: $network $local_fs $remote_fs $syslog +# Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Metronome XMPP Server @@ -13,10 +13,11 @@ set -e # /etc/init.d/metronome: start and stop Metronome XMPP server +NAME=metronome +USER=metronome DAEMON=/usr/bin/metronome PIDPATH=/var/run/metronome PIDFILE="$PIDPATH"/metronome.pid -RUNTIME=/usr/bin/lua5.1 NICE= MAXFDS= @@ -25,77 +26,94 @@ IOSCHED= test -x "$DAEMON" || exit 0 +. /lib/lsb/init-functions + if [ -f /etc/default/metronome ] ; then . /etc/default/metronome fi -if [ ! -d "$PIDPATH" ]; then - mkdir "$PIDPATH"; - chown metronome:adm "$PIDPATH"; -fi - -# Check that user 'metronome' exists -check_user() { - if ! getent passwd metronome >/dev/null; then - exit 1; - fi -} - start_opts() { - test -z "$NICE" || echo -n " --nicelevel $NICE" - test -z "$CPUSCHED" || echo -n " --procsched $CPUSCHED" - test -z "$IOSCHED" || echo -n " --iosched $IOSCHED" + test -z "$NICE" || echo -n " --nicelevel $NICE" + test -z "$CPUSCHED" || echo -n " --procsched $CPUSCHED" + test -z "$IOSCHED" || echo -n " --iosched $IOSCHED" } -. /lib/lsb/init-functions +start_metronome () { + mkdir -p `dirname $PIDFILE` + chown metronome:adm `dirname $PIDFILE` + if start-stop-daemon --start --quiet --pidfile "$PIDFILE" \ + --chuid "$USER" --oknodo --user "$USER" --name lua5.1 \ + $(start_opts) --startas "$DAEMON"; + then + return 0 + else + return 1 + fi +} -test -z "$MAXFDS" || ulimit -n "$MAXFDS" +stop_metronome () { + if start-stop-daemon --stop --quiet --retry 30 \ + --oknodo --pidfile "$PIDFILE" --user "$USER" --name lua5.1; + then + return 0 + else + return 1 + fi +} + +signal_metronome () { + if start-stop-daemon --stop --quiet --pidfile "$PIDFILE" \ + --user "$USER" --name lua5.1 --oknodo --signal $1; + then + return 0 + else + return 1 + fi +} case "$1" in start) - check_user - log_daemon_msg "Starting Metronome XMPP Server" "metronome" - - if start-stop-daemon --start --quiet --oknodo --pidfile "$PIDFILE" --chuid metronome $(start_opts) --exec "$RUNTIME" -- "$DAEMON"; then - log_end_msg 0 - else - log_end_msg 1 - fi - ;; + log_daemon_msg "Starting Metronome XMPP Server" "metronome" + if start_metronome; then + log_end_msg 0; + else + log_end_msg 1; + fi + ;; stop) - log_daemon_msg "Stopping Metronome XMPP Server" "metronome" - if start-stop-daemon --stop --retry 30 --quiet --oknodo --pidfile "$PIDFILE"; then - log_end_msg 0 - else - log_end_msg 1 - fi - ;; + log_daemon_msg "Stopping Metronome XMPP Server" "metronome" + if stop_metronome; then + log_end_msg 0; + else + log_end_msg 1; + fi + ;; force-reload|restart) - log_daemon_msg "Restarting Metronome XMPP Server" "metronome" - - start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile "$PIDFILE" - - check_user log_end_msg - - if start-stop-daemon --start --quiet --oknodo --pidfile "$PIDFILE" --chuid metronome $(start_opts) --exec "$RUNTIME" -- "$DAEMON"; then - log_end_msg 0 - else - log_end_msg 1 - fi - ;; + log_daemon_msg "Restarting Metronome XMPP Server" "metronome" + + stop_metronome + + if start_metronome; then + log_end_msg 0; + else + log_end_msg 1; + fi + ;; reload) - log_daemon_msg "Reloading Metronome XMPP Server" "metronome" - - if start-stop-daemon --stop --quiet --pidfile "$PIDFILE" --signal 1; then - log_end_msg 0 - else - log_end_msg 1 - fi + log_daemon_msg "Reloading Metronome XMPP Server" "metronome" + + if signal_metronome 1; then + log_end_msg 0; + else + log_end_msg 1; + fi + ;; + status) + status_of_proc -p $PIDFILE $DAEMON $NAME ;; *) - log_action_msg "Usage: /etc/init.d/metronome {start|stop|restart|reload}" - exit 1 + log_action_msg "Usage: /etc/init.d/metronome {start|stop|restart|reload|status}" + exit 1 esac exit 0 - diff --git a/data/templates/metronome/metronome.logrotate b/data/templates/metronome/metronome.logrotate index aa145429..ccdc2feb 100644 --- a/data/templates/metronome/metronome.logrotate +++ b/data/templates/metronome/metronome.logrotate @@ -1,11 +1,11 @@ /var/log/metronome/metronome.log /var/log/metronome/metronome.err { - daily - rotate 14 - compress - create 640 metronome adm - postrotate - /etc/init.d/metronome reload > /dev/null - endscript - sharedscripts - missingok + daily + rotate 14 + compress + create 640 metronome adm + postrotate + /etc/init.d/metronome reload > /dev/null + endscript + sharedscripts + missingok } diff --git a/data/templates/metronome/modules/mod_legacyauth.lua b/data/templates/metronome/modules/mod_legacyauth.lua index cee591c9..3ee8b978 100644 --- a/data/templates/metronome/modules/mod_legacyauth.lua +++ b/data/templates/metronome/modules/mod_legacyauth.lua @@ -12,8 +12,8 @@ local st = require "util.stanza"; local t_concat = table.concat; local secure_auth_only = module:get_option("c2s_require_encryption") - or module:get_option("require_encryption") - or not(module:get_option("allow_unencrypted_plain_auth")); + or module:get_option("require_encryption") + or not(module:get_option("allow_unencrypted_plain_auth")); local sessionmanager = require "core.sessionmanager"; local usermanager = require "core.usermanager"; @@ -22,66 +22,66 @@ local resourceprep = require "util.encodings".stringprep.resourceprep; module:add_feature("jabber:iq:auth"); module:hook("stream-features", function(event) - local origin, features = event.origin, event.features; - if secure_auth_only and not origin.secure then - -- Sorry, not offering to insecure streams! - return; - elseif not origin.username then - features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up(); - end + local origin, features = event.origin, event.features; + if secure_auth_only and not origin.secure then + -- Sorry, not offering to insecure streams! + return; + elseif not origin.username then + features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up(); + end end); module:hook("stanza/iq/jabber:iq:auth:query", function(event) - local session, stanza = event.origin, event.stanza; + local session, stanza = event.origin, event.stanza; - if session.type ~= "c2s_unauthed" then - (session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections.")); - return true; - end + if session.type ~= "c2s_unauthed" then + (session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections.")); + return true; + end - if secure_auth_only and not session.secure then - session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server")); - return true; - end - - local username = stanza.tags[1]:child_with_name("username"); - local password = stanza.tags[1]:child_with_name("password"); - local resource = stanza.tags[1]:child_with_name("resource"); - if not (username and password and resource) then - local reply = st.reply(stanza); - session.send(reply:query("jabber:iq:auth") - :tag("username"):up() - :tag("password"):up() - :tag("resource"):up()); - else - username, password, resource = t_concat(username), t_concat(password), t_concat(resource); - username = nodeprep(username); - resource = resourceprep(resource) - if not (username and resource) then - session.send(st.error_reply(stanza, "modify", "bad-request")); - return true; - end - if usermanager.test_password(username, session.host, password) then - -- Authentication successful! - local success, err = sessionmanager.make_authenticated(session, username); - if success then - local err_type, err_msg; - success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource); - if not success then - session.send(st.error_reply(stanza, err_type, err, err_msg)); - session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager? - return true; - elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth - session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session.")); - session:close(); -- FIXME undo resource bind and auth instead of closing the session? - return true; - end - end - session.send(st.reply(stanza)); - else - session.send(st.error_reply(stanza, "auth", "not-authorized")); - end - end - return true; + if secure_auth_only and not session.secure then + session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server")); + return true; + end + + local username = stanza.tags[1]:child_with_name("username"); + local password = stanza.tags[1]:child_with_name("password"); + local resource = stanza.tags[1]:child_with_name("resource"); + if not (username and password and resource) then + local reply = st.reply(stanza); + session.send(reply:query("jabber:iq:auth") + :tag("username"):up() + :tag("password"):up() + :tag("resource"):up()); + else + username, password, resource = t_concat(username), t_concat(password), t_concat(resource); + username = nodeprep(username); + resource = resourceprep(resource) + if not (username and resource) then + session.send(st.error_reply(stanza, "modify", "bad-request")); + return true; + end + if usermanager.test_password(username, session.host, password) then + -- Authentication successful! + local success, err = sessionmanager.make_authenticated(session, username); + if success then + local err_type, err_msg; + success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource); + if not success then + session.send(st.error_reply(stanza, err_type, err, err_msg)); + session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager? + return true; + elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth + session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session.")); + session:close(); -- FIXME undo resource bind and auth instead of closing the session? + return true; + end + end + session.send(st.reply(stanza)); + else + session.send(st.error_reply(stanza, "auth", "not-authorized")); + end + end + return true; end); diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index ceac04ad..cd09cc9d 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -397,7 +397,10 @@ def _get_diff(string, filename): with open(filename, 'r') as f: file_lines = f.readlines() - new_lines = string.splitlines(1) + string = string + '\n' + new_lines = string.splitlines(True) + while '\n' == file_lines[-1]: + del file_lines[-1] return difflib.unified_diff(file_lines, new_lines) except IOError: return [] @@ -543,14 +546,13 @@ def service_safecopy(service, new_conf_file, conf_file, force=False): if force or previous_hash == current_hash: with open(conf_file, 'w') as f: f.write(new_conf) new_hash = _hash(conf_file) - if current_hash != new_hash: + if previous_hash != new_hash: regenerated = True elif len(diff) == 0: new_hash = _hash(conf_file) else: new_hash = previous_hash - if os.isatty(1) and \ - (len(previous_hash) == 32 or previous_hash[-32:] != current_hash): + if (len(previous_hash) == 32 or previous_hash[-32:] != current_hash): msignals.display( m18n.n('service_configuration_conflict', conf_file), 'warning' From ef1ad685fd6bc33e744302bb450171c98b1b0739 Mon Sep 17 00:00:00 2001 From: kload Date: Tue, 29 Sep 2015 14:36:46 +0000 Subject: [PATCH 43/86] [fix] Indent properly to avoid unwanted differences --- data/templates/slapd/ldap.conf | 12 ++++++------ data/templates/slapd/mailserver.schema | 7 ++++--- data/templates/slapd/slapd.conf | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/data/templates/slapd/ldap.conf b/data/templates/slapd/ldap.conf index bfd86e8a..406b5c17 100644 --- a/data/templates/slapd/ldap.conf +++ b/data/templates/slapd/ldap.conf @@ -5,14 +5,14 @@ # See ldap.conf(5) for details # This file should be world readable but not world writable. -#BASE dc=example,dc=com -#URI ldap://ldap.example.com ldap://ldap-master.example.com:666 +#BASE dc=example,dc=com +#URI ldap://ldap.example.com ldap://ldap-master.example.com:666 -#SIZELIMIT 12 -#TIMELIMIT 15 -#DEREF never +#SIZELIMIT 12 +#TIMELIMIT 15 +#DEREF never # TLS certificates (needed for GnuTLS) -TLS_CACERT /etc/ssl/certs/ca-certificates.crt +TLS_CACERT /etc/ssl/certs/ca-certificates.crt sudoers_base ou=sudo,dc=yunohost,dc=org diff --git a/data/templates/slapd/mailserver.schema b/data/templates/slapd/mailserver.schema index 55374ce4..23d0d24b 100644 --- a/data/templates/slapd/mailserver.schema +++ b/data/templates/slapd/mailserver.schema @@ -47,9 +47,10 @@ attributetype ( 1.3.6.1.4.1.40328.1.20.2.6 attributetype ( 1.3.6.1.4.1.40328.1.20.2.7 NAME 'mailuserquota' - DESC 'Mailbox quota for a user in kilo-bytes' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + DESC 'Mailbox quota for a user' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} SINGLE-VALUE ) # Mail Account Objectclass objectclass ( 1.3.6.1.4.1.40328.1.1.2.1 diff --git a/data/templates/slapd/slapd.conf b/data/templates/slapd/slapd.conf index 3b0e3cf2..e5ac8801 100644 --- a/data/templates/slapd/slapd.conf +++ b/data/templates/slapd/slapd.conf @@ -29,8 +29,8 @@ password-hash {SSHA} loglevel 256 # Where the dynamically loaded modules are stored -modulepath /usr/lib/ldap -moduleload back_hdb +modulepath /usr/lib/ldap +moduleload back_hdb moduleload memberof # The maximum number of entries that is returned for a search operation @@ -44,13 +44,13 @@ tool-threads 1 # Specific Backend Directives for hdb: # Backend specific directives apply to this backend until another # 'backend' directive occurs -backend hdb +backend hdb ####################################################################### # Specific Backend Directives for 'other': # Backend specific directives apply to this backend until another # 'backend' directive occurs -#backend +#backend ####################################################################### # Specific Directives for database #1, of type hdb: @@ -85,7 +85,7 @@ dbconfig set_lk_max_lockers 1500 # Indexing options for database #1 index objectClass eq -index uid eq,sub +index uid eq,sub index entryCSN,entryUUID eq # Save the time that the entry gets modified, for database #1 @@ -96,7 +96,7 @@ lastmod on checkpoint 512 30 # Where to store the replica logs for database #1 -# replogfile /var/lib/ldap/replog +# replogfile /var/lib/ldap/replog # The userPassword by default can be changed # by the entry owning it if they are authenticated. @@ -105,7 +105,7 @@ checkpoint 512 30 # These access lines apply to database #1 only access to attrs=userPassword by dn="cn=admin,dc=yunohost,dc=org" write - by anonymous auth + by anonymous auth by self write by * none @@ -130,8 +130,8 @@ access to dn.base="" by * read # can read everything. access to * by dn="cn=admin,dc=yunohost,dc=org" write - by group/groupOfNames/Member="cn=admin,ou=groups,dc=yunohost,dc=org" write - by * read + by group/groupOfNames/Member="cn=admin,ou=groups,dc=yunohost,dc=org" write + by * read ####################################################################### # Specific Directives for database #2, of type 'other' (can be hdb too): @@ -140,4 +140,4 @@ access to * #database # The base of your directory for database #2 -#suffix "dc=debian,dc=org" +#suffix "dc=debian,dc=org" From aa6a277e20bd0ad00ad26a19d3efc5b908fa0ef7 Mon Sep 17 00:00:00 2001 From: kload Date: Tue, 29 Sep 2015 15:30:43 -0400 Subject: [PATCH 44/86] [fix] Slapd default spacing --- data/templates/nslcd/nslcd.conf | 15 +++++++++++---- data/templates/slapd/slapd.default | 4 ++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/data/templates/nslcd/nslcd.conf b/data/templates/nslcd/nslcd.conf index 9774613f..c927b5f3 100644 --- a/data/templates/nslcd/nslcd.conf +++ b/data/templates/nslcd/nslcd.conf @@ -10,22 +10,29 @@ gid nslcd uri ldap://localhost/ # The search base that will be used for all queries. -base dc=yunohost,dc=org +base dc=yunohost,dc=org # The LDAP protocol version to use. #ldap_version 3 # The DN to bind with for normal lookups. -#binddn -#bindpw +#binddn cn=annonymous,dc=example,dc=net +#bindpw secret # The DN used for password modifications by root. #rootpwmoddn cn=admin,dc=example,dc=com # SSL options #ssl off -#tls_reqcert +#tls_reqcert never +tls_cacertfile /etc/ssl/certs/ca-certificates.crt # The search scope. #scope sub + + + + + + diff --git a/data/templates/slapd/slapd.default b/data/templates/slapd/slapd.default index 9cd3b2e9..372b8f4a 100644 --- a/data/templates/slapd/slapd.default +++ b/data/templates/slapd/slapd.default @@ -1,7 +1,7 @@ # Default location of the slapd.conf file or slapd.d cn=config directory. If # empty, use the compiled-in default (/etc/ldap/slapd.d with a fallback to # /etc/ldap/slapd.conf). -SLAPD_CONF=/etc/ldap/slapd.conf +SLAPD_CONF= # System account to run the slapd server under. If empty the server # will run as root. @@ -21,7 +21,7 @@ SLAPD_PIDFILE= # sockets. # Example usage: # SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///" -SLAPD_SERVICES="ldap://127.0.0.1/ ldapi://127.0.0.1/" +SLAPD_SERVICES="ldap:/// ldapi:///" # If SLAPD_NO_START is set, the init script will not start or restart # slapd (but stop will still work). Uncomment this if you are From d19fc96fdfc5cfd2dd0225d7437c8a61cb23ab9b Mon Sep 17 00:00:00 2001 From: kload Date: Tue, 29 Sep 2015 15:58:28 -0400 Subject: [PATCH 45/86] [enh] Postfix regen conf script --- data/hooks/conf_regen/19-postfix | 56 ++++++++ data/templates/postfix/main.cf-ipv4.j2 | 127 ------------------ .../postfix/{main.cf.j2 => main.cf.sed} | 39 ++++-- data/templates/postfix/smtp_reply_filter | 8 ++ .../postgrey => postgrey/postgrey.default} | 0 5 files changed, 93 insertions(+), 137 deletions(-) create mode 100644 data/hooks/conf_regen/19-postfix delete mode 100644 data/templates/postfix/main.cf-ipv4.j2 rename data/templates/postfix/{main.cf.j2 => main.cf.sed} (72%) create mode 100644 data/templates/postfix/smtp_reply_filter rename data/templates/{postfix/postgrey => postgrey/postgrey.default} (100%) diff --git a/data/hooks/conf_regen/19-postfix b/data/hooks/conf_regen/19-postfix new file mode 100644 index 00000000..38061ee6 --- /dev/null +++ b/data/hooks/conf_regen/19-postfix @@ -0,0 +1,56 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s postfix \ + $1 $2 \ + --force + else + sudo yunohost service safecopy \ + -s postfix \ + $1 $2 + fi +} + +cd /usr/share/yunohost/templates/postfix + +# Copy plain single configuration files +files="header_check +ldap-accounts.cf +ldap-aliases.cf +ldap-domains.cf +master.cf +sender_canonical +smtp_reply_filter" + +for file in $files; do + safe_copy $file /etc/postfix/$file +done + +main_domain=$(cat /etc/yunohost/current_host) + +# Replace main domain in the main configuration file +cat main.cf.sed \ + | sed "s/{{ main_domain }}/$main_domain/g" \ + | sudo tee main.cf + +# And adapt it to IPv4-only hosts +if [ ! -f /proc/net/if_inet6 ]; then + sudo sed -i \ + 's/ \[::ffff:127.0.0.0\]\/104 \[::1\]\/128//g' \ + main.cf + + sudo sed -i \ + 's/inet_interfaces = all/inet_interfaces = all\ninet_protocols = ipv4/' \ + main.cf +fi + +if [[ $(safe_copy main.cf /etc/postfix/main.cf) == "True" ]]; then + sudo service postfix restart +else + sudo service postfix reload +fi diff --git a/data/templates/postfix/main.cf-ipv4.j2 b/data/templates/postfix/main.cf-ipv4.j2 deleted file mode 100644 index f2cf0457..00000000 --- a/data/templates/postfix/main.cf-ipv4.j2 +++ /dev/null @@ -1,127 +0,0 @@ -# See /usr/share/postfix/main.cf.dist for a commented, more complete version - - -# Debian specific: Specifying a file name will cause the first -# line of that file to be used as the name. The Debian default -# is /etc/mailname. -#myorigin = /etc/mailname - -smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) -biff = no - -# appending .domain is the MUA's job. -append_dot_mydomain = no - -# Uncomment the next line to generate "delayed mail" warnings -#delay_warning_time = 4h - -readme_directory = no - -# TLS parameters -smtpd_tls_cert_file=/etc/ssl/certs/yunohost_crt.pem -smtpd_tls_key_file=/etc/ssl/private/yunohost_key.pem -smtpd_tls_CAfile = /etc/ssl/certs/ca-yunohost_crt.pem -smtpd_use_tls=yes -smtpd_tls_exclude_ciphers = aNULL, MD5, DES, ADH -smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache -smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache - -# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for -# information on enabling SSL in the smtp client. - -myhostname = {{ domain }} -alias_maps = hash:/etc/aliases -alias_database = hash:/etc/aliases -mydomain = {{ domain }} -mydestination = localhost -relayhost = -mynetworks = 127.0.0.0/8 -mailbox_command = procmail -a "$EXTENSION" -mailbox_size_limit = 0 -recipient_delimiter = + -inet_interfaces = all -inet_protocols = ipv4 - -#### add yunohost #### -message_size_limit = 10240000 - -# Virtual Domains Control -virtual_mailbox_domains = ldap:/etc/postfix/ldap-domains.cf -virtual_mailbox_maps = ldap:/etc/postfix/ldap-accounts.cf -virtual_mailbox_base = -virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf -virtual_alias_domains = -virtual_minimum_uid = 100 -virtual_uid_maps = static:vmail -virtual_gid_maps = static:mail - -# Dovecot LDA -virtual_transport = dovecot -dovecot_destination_recipient_limit = 1 - -# Enable SASL authentication for the smtpd daemon -smtpd_sasl_auth_enable = yes -smtpd_sasl_type = dovecot -smtpd_sasl_path = private/auth -# Fix some outlook's bugs -broken_sasl_auth_clients = yes -# Reject anonymous connections -smtpd_sasl_security_options = noanonymous -smtpd_sasl_local_domain = - - -# Use AMaVis -content_filter = amavis:[127.0.0.1]:10024 - -# Wait until the RCPT TO command before evaluating restrictions -smtpd_delay_reject = yes - -# Basics Restrictions -smtpd_helo_required = yes -strict_rfc821_envelopes = yes - -# Requirements for the connecting server -smtpd_client_restrictions = - permit_mynetworks, - permit_sasl_authenticated, - reject_rbl_client bl.spamcop.net, - reject_rbl_client cbl.abuseat.org, - reject_rbl_client sbl-xbl.spamhaus.org, - permit - -# Requirements for the HELO statement -smtpd_helo_restrictions = - permit_mynetworks, - permit_sasl_authenticated, - reject_non_fqdn_hostname, - reject_invalid_hostname, - permit - -# Requirements for the sender address -smtpd_sender_restrictions = - permit_mynetworks, - permit_sasl_authenticated, - reject_non_fqdn_sender, - reject_unknown_sender_domain, - permit - -# Requirement for the recipient address -smtpd_recipient_restrictions = - permit_mynetworks, - permit_sasl_authenticated, - reject_non_fqdn_recipient, - reject_unknown_recipient_domain, - reject_unauth_destination, - check_policy_service unix:private/policy-spf - check_policy_service inet:127.0.0.1:10023 - permit - -# Use SPF -policy-spf_time_limit = 3600s - -# SRS -sender_canonical_maps = regexp:/etc/postfix/sender_canonical -sender_canonical_classes = envelope_sender - -# Ignore some headers -smtp_header_checks = regexp:/etc/postfix/header_checks diff --git a/data/templates/postfix/main.cf.j2 b/data/templates/postfix/main.cf.sed similarity index 72% rename from data/templates/postfix/main.cf.j2 rename to data/templates/postfix/main.cf.sed index 6c1052dc..fd81ae64 100644 --- a/data/templates/postfix/main.cf.j2 +++ b/data/templates/postfix/main.cf.sed @@ -6,7 +6,7 @@ # is /etc/mailname. #myorigin = /etc/mailname -smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) +smtpd_banner = $myhostname Service ready biff = no # appending .domain is the MUA's job. @@ -17,22 +17,39 @@ append_dot_mydomain = no readme_directory = no -# TLS parameters +# -- TLS for incoming connections +# By default, TLS is disabled in the Postfix SMTP server, so no difference to +# plain Postfix is visible. Explicitly switch it on with "smtpd_tls_security_level = may". +smtpd_tls_security_level=may + +# Sending AUTH data over an unencrypted channel poses a security risk. +# When TLS layer encryption is optional ("smtpd_tls_security_level = may"), it +# may however still be useful to only offer AUTH when TLS is active. To maintain +# compatibility with non-TLS clients, the default is to accept AUTH without +# encryption. In order to change this behavior, we set "smtpd_tls_auth_only = yes". +smtpd_tls_auth_only=yes smtpd_tls_cert_file=/etc/ssl/certs/yunohost_crt.pem smtpd_tls_key_file=/etc/ssl/private/yunohost_key.pem smtpd_tls_CAfile = /etc/ssl/certs/ca-yunohost_crt.pem -smtpd_use_tls=yes -smtpd_tls_exclude_ciphers = aNULL, MD5, DES, ADH +smtpd_tls_exclude_ciphers = aNULL, MD5, DES, ADH, RC4 smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache +smtpd_tls_loglevel=1 +smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 +smtpd_tls_mandatory_ciphers=high + +# -- TLS for outgoing connections +# Use TLS if this is supported by the remote SMTP server, otherwise use plaintext. +smtp_tls_security_level=may smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache +smtp_tls_loglevel=1 # See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for # information on enabling SSL in the smtp client. -myhostname = {{ domain }} +myhostname = {{ main_domain }} alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases -mydomain = {{ domain }} +mydomain = {{ main_domain }} mydestination = localhost relayhost = mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 @@ -41,8 +58,8 @@ mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all -#### add yunohost #### -message_size_limit = 10240000 +#### Fit to the maximum message size allowed by GMail or Yahoo #### +message_size_limit = 26214400 # Virtual Domains Control virtual_mailbox_domains = ldap:/etc/postfix/ldap-domains.cf @@ -85,7 +102,7 @@ smtpd_client_restrictions = permit_sasl_authenticated, reject_rbl_client bl.spamcop.net, reject_rbl_client cbl.abuseat.org, - reject_rbl_client sbl-xbl.spamhaus.org, + reject_rbl_client zen.spamhaus.org, permit # Requirements for the HELO statement @@ -115,7 +132,7 @@ smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10023 permit -#Use SPF +# Use SPF policy-spf_time_limit = 3600s # SRS @@ -124,3 +141,5 @@ sender_canonical_classes = envelope_sender # Ignore some headers smtp_header_checks = regexp:/etc/postfix/header_checks + +smtp_reply_filter = pcre:/etc/postfix/smtp_reply_filter diff --git a/data/templates/postfix/smtp_reply_filter b/data/templates/postfix/smtp_reply_filter new file mode 100644 index 00000000..5f15648f --- /dev/null +++ b/data/templates/postfix/smtp_reply_filter @@ -0,0 +1,8 @@ +# Google Mail bounces email sent via IPv6, while this works ok with IPv4. +# +# Convert Google Mail IPv6 complaint permanent error into a temporary error. +# Turn 550 error containing gsmtp in the message into 450 error. +# This way Postfix will attempt to deliver this e-mail using another MX +# (via IPv4). +# +/^5(\d\d )5(.*information. \S+ - gsmtp.*)/ 4${1}4$2 diff --git a/data/templates/postfix/postgrey b/data/templates/postgrey/postgrey.default similarity index 100% rename from data/templates/postfix/postgrey rename to data/templates/postgrey/postgrey.default From 44bdeeb29224af8a684e4b4a59ef96a62245fa7b Mon Sep 17 00:00:00 2001 From: kload Date: Tue, 29 Sep 2015 19:04:16 -0400 Subject: [PATCH 46/86] [enh] Dovecot and postgrey regen conf script --- data/hooks/conf_regen/22-postgrey | 23 ++++++ data/hooks/conf_regen/25-dovecot | 52 ++++++++++++++ data/templates/dovecot/dovecot-ipv4.conf.j2 | 71 ------------------- data/templates/dovecot/dovecot-ldap.conf | 2 +- .../{dovecot.conf.j2 => dovecot.conf.sed} | 27 ++++++- data/templates/postfix/master.cf | 12 ++-- 6 files changed, 106 insertions(+), 81 deletions(-) create mode 100644 data/hooks/conf_regen/22-postgrey create mode 100644 data/hooks/conf_regen/25-dovecot delete mode 100644 data/templates/dovecot/dovecot-ipv4.conf.j2 rename data/templates/dovecot/{dovecot.conf.j2 => dovecot.conf.sed} (69%) diff --git a/data/hooks/conf_regen/22-postgrey b/data/hooks/conf_regen/22-postgrey new file mode 100644 index 00000000..b1f924a0 --- /dev/null +++ b/data/hooks/conf_regen/22-postgrey @@ -0,0 +1,23 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s postgrey \ + $1 $2 \ + --force + else + sudo yunohost service safecopy \ + -s postgrey \ + $1 $2 + fi +} + +cd /usr/share/yunohost/templates/postgrey + +if [[ "$(safe_copy postgrey.default /etc/default/postgrey)" == "True" ]]; then + sudo service nslcd restart +fi diff --git a/data/hooks/conf_regen/25-dovecot b/data/hooks/conf_regen/25-dovecot new file mode 100644 index 00000000..e8d2187d --- /dev/null +++ b/data/hooks/conf_regen/25-dovecot @@ -0,0 +1,52 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s dovecot $1 $2 --force + else + sudo yunohost service safecopy \ + -s dovecot $1 $2 + fi +} + +cd /usr/share/yunohost/templates/dovecot + +# Create vmail user +sudo id vmail > /dev/null 2>&1 \ + || sudo adduser --system --ingroup mail --uid 500 vmail + + +# Replace main domain in the main configuration file +main_domain=$(cat /etc/yunohost/current_host) +cat dovecot.conf.sed \ + | sed "s/{{ main_domain }}/$main_domain/g" \ + | sudo tee dovecot.conf + + +# Handle IPv4 only systems +if [ ! -f /proc/net/if_inet6 ]; +then + sudo sed -i 's/^listen.*/listen = \*/' dovecot.conf +fi + + +safe_copy dovecot.conf /etc/dovecot/dovecot.conf +safe_copy dovecot-ldap.conf /etc/dovecot/dovecot-ldap.conf + + +# Setup Sieve +sudo rm -rf /etc/dovecot/global_script +sudo mkdir -p -m 0770 /etc/dovecot/global_script +safe_copy sa-learn-pipe.sh /usr/bin/sa-learn-pipe.sh +sudo chmod 755 /usr/bin/sa-learn-pipe.sh +safe_copy dovecot.sieve /etc/dovecot/global_script/dovecot.sieve +sudo chmod 660 /etc/dovecot/global_script/dovecot.sieve +sudo sievec /etc/dovecot/global_script/dovecot.sieve +sudo chmod 660 /etc/dovecot/global_script/dovecot.svbin + + +service dovecot reload diff --git a/data/templates/dovecot/dovecot-ipv4.conf.j2 b/data/templates/dovecot/dovecot-ipv4.conf.j2 deleted file mode 100644 index 044f0b90..00000000 --- a/data/templates/dovecot/dovecot-ipv4.conf.j2 +++ /dev/null @@ -1,71 +0,0 @@ -# 2.1.7: /etc/dovecot/dovecot.conf -# OS: Linux 3.2.0-3-686-pae i686 Debian wheezy/sid ext4 -listen = * -auth_mechanisms = plain login -login_greeting = Dovecot ready!! -mail_gid = 8 -mail_home = /var/mail/%n -mail_location = maildir:/var/mail/%n -mail_uid = 500 -passdb { - args = /etc/dovecot/dovecot-ldap.conf - driver = ldap -} -protocols = imap sieve -service auth { - unix_listener /var/spool/postfix/private/auth { - group = postfix - mode = 0660 - user = postfix - } - unix_listener auth-master { - group = mail - mode = 0660 - user = vmail - } -} - -protocol sieve { -} - -ssl_ca = Date: Tue, 29 Sep 2015 19:33:05 -0400 Subject: [PATCH 47/86] [fix] Install Sieve properly on Dovecot --- data/hooks/conf_regen/25-dovecot | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data/hooks/conf_regen/25-dovecot b/data/hooks/conf_regen/25-dovecot index e8d2187d..974fa3e0 100644 --- a/data/hooks/conf_regen/25-dovecot +++ b/data/hooks/conf_regen/25-dovecot @@ -43,10 +43,12 @@ sudo rm -rf /etc/dovecot/global_script sudo mkdir -p -m 0770 /etc/dovecot/global_script safe_copy sa-learn-pipe.sh /usr/bin/sa-learn-pipe.sh sudo chmod 755 /usr/bin/sa-learn-pipe.sh + safe_copy dovecot.sieve /etc/dovecot/global_script/dovecot.sieve -sudo chmod 660 /etc/dovecot/global_script/dovecot.sieve +sudo chmod 660 /etc/dovecot/global_script/dovecot.sieve > /dev/null 2>&1 \ + || safe_copy dovecot.sieve /etc/dovecot/global_script/dovecot.sieve sudo sievec /etc/dovecot/global_script/dovecot.sieve sudo chmod 660 /etc/dovecot/global_script/dovecot.svbin -service dovecot reload +sudo service dovecot restart From 17376896a42fd99b732d312e248453fb9658f570 Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 14:16:43 -0400 Subject: [PATCH 48/86] [fix] hdb/mdb replacement in regen script --- data/hooks/conf_regen/06-slapd | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd index 24e76d98..2ffe329e 100644 --- a/data/hooks/conf_regen/06-slapd +++ b/data/hooks/conf_regen/06-slapd @@ -18,6 +18,10 @@ function safe_copy () { cd /usr/share/yunohost/templates/slapd +# Remove legacy configuration file +sudo yunohost service saferemove -s slapd \ + /etc/ldap/slapd-yuno.conf + safe_copy mailserver.schema /etc/ldap/schema/mailserver.schema safe_copy ldap.conf /etc/ldap/ldap.conf safe_copy slapd.default /etc/default/slapd @@ -25,9 +29,11 @@ safe_copy slapd.default /etc/default/slapd # Compatibility: change from HDB to MDB on Jessie version=$(sed 's/\..*//' /etc/debian_version) if [[ "$version" == '8' ]]; then - sudo sed -i "s/ hdb/ mdb/g" slapd.conf - sudo sed -i "s/back_hdb/back_mdb/g" slapd.conf - sudo sed -i "s/dbconfig set_/#dbconfig set_/g" slapd.conf + cat slapd.conf \ + | sed "s/hdb$/mdb/g" \ + | sed "s/back_hdb/back_mdb/g" \ + | sed "s/^dbconfig set_/#dbconfig set_/g" \ + | sudo tee slapd.conf fi safe_copy slapd.conf /etc/ldap/slapd.conf From c51454b7fec3fd4b2ca74ce5b9f5a4f9e148f745 Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 14:17:45 -0400 Subject: [PATCH 49/86] [fix] Do not fail when the service is not registered properly --- lib/yunohost/service.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index cd09cc9d..000f18ef 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -199,7 +199,8 @@ def service_status(names=[]): m18n.n('service_unknown', name)) status = None - if services[name]['status'] == 'service': + if 'status' not in services[name] or \ + services[name]['status'] == 'service': status = 'service %s status' % name else: status = str(services[name]['status']) @@ -283,18 +284,11 @@ def service_regenconf(service=None, force=False): """ from yunohost.hook import hook_callback - if service is None: - # Regen ALL THE CONFIGURATIONS - hook_callback('conf_regen', args=[force]) - - msignals.display(m18n.n('services_configured'), 'success') + if service is not None: + hook_callback('conf_regen', [service], args=[force]) else: - if service not in _get_services().keys(): - raise MoulinetteError(errno.EINVAL, m18n.n('service_unknown', service)) - - hook_callback('conf_regen', [service] , args=[force]) - - msignals.display(m18n.n('service_configured', service), 'success') + hook_callback('conf_regen', args=[force]) + msignals.display(m18n.n('services_configured'), 'success') def _run_service_command(action, service): @@ -436,6 +430,7 @@ def service_saferemove(service, conf_file, force=False): """ deleted = False + services = _get_services() if not os.path.exists(conf_file): try: @@ -443,8 +438,6 @@ def service_saferemove(service, conf_file, force=False): except KeyError: pass return True - services = _get_services() - # Backup existing file date = time.strftime("%Y%m%d.%H%M%S") conf_backup_file = conf_backup_dir + conf_file +'-'+ date From 67b19bf4313d7d4fd76b85c8c97869ebf6de977f Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 14:18:32 -0400 Subject: [PATCH 50/86] [enh] Add spamassassin regen conf script --- data/hooks/conf_regen/28-spamassassin | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 data/hooks/conf_regen/28-spamassassin diff --git a/data/hooks/conf_regen/28-spamassassin b/data/hooks/conf_regen/28-spamassassin new file mode 100644 index 00000000..e55f10dc --- /dev/null +++ b/data/hooks/conf_regen/28-spamassassin @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s spamassassin $1 $2 --force + else + sudo yunohost service safecopy \ + -s spamassassin $1 $2 + fi +} + +cd /usr/share/yunohost/templates/spamassassin + +safe_copy spamassassin.default /etc/default/spamassassin +safe_copy local.cf /etc/spamassassin/local.cf + +sudo service spamassassin restart From 93052906dc2e7ae77994320cbab6db65c3aab943 Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 15:02:05 -0400 Subject: [PATCH 51/86] [enh] Add amavis conf regen script --- data/hooks/conf_regen/31-amavis | 37 +++++++++++++++++++ data/templates/amavis/20-debian_defaults | 4 +- .../amavis/{50-user.j2 => 50-user.sed} | 4 +- 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 data/hooks/conf_regen/31-amavis rename data/templates/amavis/{50-user.j2 => 50-user.sed} (89%) diff --git a/data/hooks/conf_regen/31-amavis b/data/hooks/conf_regen/31-amavis new file mode 100644 index 00000000..f25c70fe --- /dev/null +++ b/data/hooks/conf_regen/31-amavis @@ -0,0 +1,37 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s amavis $1 $2 --force + else + sudo yunohost service safecopy \ + -s amavis $1 $2 + fi +} + +cd /usr/share/yunohost/templates/amavis + +sudo mkdir -p /etc/amavis/conf.d/ + +# Copy plain single configuration files +files="05-domain_id +05-node_id +15-content_filter_mode +20-debian_defaults" + +for file in $files; do + safe_copy $file /etc/amavis/conf.d/$file +done + +main_domain=$(cat /etc/yunohost/current_host) +cat 50-user.sed \ + | sed "s/{{ main_domain }}/$main_domain/g" \ + | sudo tee 50-user +safe_copy 50-user /etc/amavis/conf.d/50-user + + +sudo service amavis restart diff --git a/data/templates/amavis/20-debian_defaults b/data/templates/amavis/20-debian_defaults index fb8d835d..83e553d2 100644 --- a/data/templates/amavis/20-debian_defaults +++ b/data/templates/amavis/20-debian_defaults @@ -119,8 +119,8 @@ $banned_filename_re = new_RE( qr'^application/x-msdos-program$'i, qr'^application/hta$'i, -# qr'^application/x-msmetafile$'i, # Windows Metafile MIME type -# qr'^\.wmf$', # Windows Metafile file(1) type +# qr'^application/x-msmetafile$'i, # Windows Metafile MIME type +# qr'^\.wmf$', # Windows Metafile file(1) type # qr'^message/partial$'i, qr'^message/external-body$'i, # rfc2046 MIME types diff --git a/data/templates/amavis/50-user.j2 b/data/templates/amavis/50-user.sed similarity index 89% rename from data/templates/amavis/50-user.j2 rename to data/templates/amavis/50-user.sed index 129da4f2..b0e7ce14 100644 --- a/data/templates/amavis/50-user.j2 +++ b/data/templates/amavis/50-user.sed @@ -8,9 +8,9 @@ use strict; # the directives you can use in this file # -$myhostname = "{{ domain }}"; +$myhostname = "{{ main_domain }}"; -$mydomain = "{{ domain }}"; +$mydomain = "{{ main_domain }}"; # Enable LDAP support $enable_ldap = 1; From 8838c692c9acdb98526b110129911103f745bdef Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 16:20:32 -0400 Subject: [PATCH 52/86] [enh] Add MySQL, avahi and glances regen script --- data/hooks/conf_regen/34-mysql | 20 ++++++ data/hooks/conf_regen/37-avahi-daemon | 20 ++++++ data/hooks/conf_regen/40-glances | 20 ++++++ data/templates/avahi-daemon/avahi-daemon.conf | 68 +++++++++++++++++++ data/templates/glances/glances.default | 7 +- 5 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 data/hooks/conf_regen/34-mysql create mode 100644 data/hooks/conf_regen/37-avahi-daemon create mode 100644 data/hooks/conf_regen/40-glances create mode 100644 data/templates/avahi-daemon/avahi-daemon.conf diff --git a/data/hooks/conf_regen/34-mysql b/data/hooks/conf_regen/34-mysql new file mode 100644 index 00000000..62d9d2b2 --- /dev/null +++ b/data/hooks/conf_regen/34-mysql @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s mysql $1 $2 --force + else + sudo yunohost service safecopy \ + -s mysql $1 $2 + fi +} + +cd /usr/share/yunohost/templates/mysql + +if [[ "$(safe_copy my.cnf /etc/mysql/my.cnf)" == "True" ]]; then + sudo service mysql restart +fi diff --git a/data/hooks/conf_regen/37-avahi-daemon b/data/hooks/conf_regen/37-avahi-daemon new file mode 100644 index 00000000..31306de5 --- /dev/null +++ b/data/hooks/conf_regen/37-avahi-daemon @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s avahi-daemon $1 $2 --force + else + sudo yunohost service safecopy \ + -s avahi-daemon $1 $2 + fi +} + +cd /usr/share/yunohost/templates/avahi-daemon + +if [[ "$(safe_copy avahi-daemon.conf /etc/avahi/avahi-daemon.conf)" == "True" ]]; then + sudo service avahi-daemon restart +fi diff --git a/data/hooks/conf_regen/40-glances b/data/hooks/conf_regen/40-glances new file mode 100644 index 00000000..9f7c9c5c --- /dev/null +++ b/data/hooks/conf_regen/40-glances @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s glances $1 $2 --force + else + sudo yunohost service safecopy \ + -s glances $1 $2 + fi +} + +cd /usr/share/yunohost/templates/glances + +if [[ "$(safe_copy glances.default /etc/default/glances)" == "True" ]]; then + sudo service glances restart +fi diff --git a/data/templates/avahi-daemon/avahi-daemon.conf b/data/templates/avahi-daemon/avahi-daemon.conf new file mode 100644 index 00000000..d3542a41 --- /dev/null +++ b/data/templates/avahi-daemon/avahi-daemon.conf @@ -0,0 +1,68 @@ +# This file is part of avahi. +# +# avahi is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# avahi is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with avahi; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +# See avahi-daemon.conf(5) for more information on this configuration +# file! + +[server] +host-name=yunohost +domain-name=local +#browse-domains=0pointer.de, zeroconf.org +use-ipv4=yes +use-ipv6=yes +#allow-interfaces=eth0 +#deny-interfaces=eth1 +#check-response-ttl=no +#use-iff-running=no +#enable-dbus=yes +#disallow-other-stacks=no +#allow-point-to-point=no +#cache-entries-max=4096 +#clients-max=4096 +#objects-per-client-max=1024 +#entries-per-entry-group-max=32 +ratelimit-interval-usec=1000000 +ratelimit-burst=1000 + +[wide-area] +enable-wide-area=yes + +[publish] +#disable-publishing=no +#disable-user-service-publishing=no +#add-service-cookie=no +#publish-addresses=yes +#publish-hinfo=yes +#publish-workstation=yes +#publish-domain=yes +#publish-dns-servers=192.168.50.1, 192.168.50.2 +#publish-resolv-conf-dns-servers=yes +#publish-aaaa-on-ipv4=yes +#publish-a-on-ipv6=no + +[reflector] +#enable-reflector=no +#reflect-ipv=no + +[rlimits] +#rlimit-as= +rlimit-core=0 +rlimit-data=4194304 +rlimit-fsize=0 +rlimit-nofile=768 +rlimit-stack=4194304 +rlimit-nproc=3 diff --git a/data/templates/glances/glances.default b/data/templates/glances/glances.default index 90c29eb7..22337a0d 100644 --- a/data/templates/glances/glances.default +++ b/data/templates/glances/glances.default @@ -1,2 +1,5 @@ -DAEMON_ARGS="-B 127.0.0.1" -RUN="yes" +# Default is to launch glances with '-s' option. +DAEMON_ARGS="-s -B 127.0.0.1" + +# Change to 'true' to have glances running at startup +RUN="true" From 6f99b3f4e13c159bf9ae21105eda03efdf48a4e7 Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 17:23:59 -0400 Subject: [PATCH 53/86] [enh] Add DNSmasq regen conf script --- data/hooks/conf_regen/43-dnsmasq | 41 +++++++++++++++++++++++++++++++ data/templates/dnsmasq/domain.sed | 7 ++++++ 2 files changed, 48 insertions(+) create mode 100644 data/hooks/conf_regen/43-dnsmasq create mode 100644 data/templates/dnsmasq/domain.sed diff --git a/data/hooks/conf_regen/43-dnsmasq b/data/hooks/conf_regen/43-dnsmasq new file mode 100644 index 00000000..994566cc --- /dev/null +++ b/data/hooks/conf_regen/43-dnsmasq @@ -0,0 +1,41 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s dnsmasq $1 $2 --force + else + sudo yunohost service safecopy \ + -s dnsmasq $1 $2 + fi +} + +cd /usr/share/yunohost/templates/dnsmasq + +# Get IP address +ip=$(curl ip.yunohost.org || echo '0.0.0.0') + +# Get IPv6 IP address +ipv6=$(ip route get 2000:: | grep -q "unreachable" && echo '' \ + || ip route get 2000:: | grep -v ' fe80:' | grep -v 'cache' | awk '{print $9}') + +sudo mkdir -p /etc/dnsmasq.d + +# Copy a configuration file for each YunoHost domain +for domain in $(sudo yunohost domain list --raw); do + cat domain.sed \ + | sed "s/{{ domain }}/$domain/g" \ + | sed "s/{{ ip }}/$ip/g" \ + | sudo tee $domain + + if [[ "$ipv6" != "" ]]; then + echo "address=/$domain/$ipv6" | sudo tee -a $domain + fi + + safe_copy $domain /etc/dnsmasq.d/$domain +done + +sudo service dnsmasq reload diff --git a/data/templates/dnsmasq/domain.sed b/data/templates/dnsmasq/domain.sed new file mode 100644 index 00000000..9966d1fd --- /dev/null +++ b/data/templates/dnsmasq/domain.sed @@ -0,0 +1,7 @@ +resolv-file= +address=/{{ domain }}/{{ ip }} +txt-record={{ domain }},"v=spf1 mx a -all" +mx-host={{ domain }},{{ domain }},5 +srv-host=_xmpp-client._tcp.{{ domain }},{{ domain }},5222,0,5 +srv-host=_xmpp-server._tcp.{{ domain }},{{ domain }},5269,0,5 +srv-host=_jabber._tcp.{{ domain }},{{ domain }},5269,0,5 From 1baa89dea34a5f6a192b344cfa0de6e37484db4e Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 17:48:06 -0400 Subject: [PATCH 54/86] [fix] Properly set permissions on LDAP directory --- data/hooks/conf_regen/06-slapd | 1 + 1 file changed, 1 insertion(+) diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd index 2ffe329e..b711ae0b 100644 --- a/data/hooks/conf_regen/06-slapd +++ b/data/hooks/conf_regen/06-slapd @@ -44,5 +44,6 @@ sudo chown -R openldap:openldap /etc/ldap/schema/ sudo chown -R openldap:openldap /etc/ldap/slapd.d/ sudo slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ +sudo chown -R openldap:openldap /etc/ldap/slapd.d/ sudo service slapd force-reload From 8a2c607933b21a429f421dd801bb7270c6d6f633 Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 19:02:15 -0400 Subject: [PATCH 55/86] [fix] Remove unused domain configurations on impacted services --- data/hooks/conf_regen/12-metronome | 23 ++++++++++++++++++++++- data/hooks/conf_regen/15-nginx | 10 ++++++++++ data/hooks/conf_regen/43-dnsmasq | 7 +++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/data/hooks/conf_regen/12-metronome b/data/hooks/conf_regen/12-metronome index c0824c33..d43660c5 100644 --- a/data/hooks/conf_regen/12-metronome +++ b/data/hooks/conf_regen/12-metronome @@ -41,8 +41,13 @@ safe_copy metronome.logrotate /etc/logrotate.d/metronome need_restart=False sudo mkdir -p /etc/metronome/conf.d +domain_list=$(sudo yunohost domain list --raw) + # Copy a configuration file for each YunoHost domain -for domain in $(sudo yunohost domain list --raw); do +for domain in $domain_list; do + sanitzed_domain="$(echo $domain | sed 's/\./%2e/g')" + sudo mkdir -p /var/lib/metronome/$sanitzed_domain/pep + cat domain.cfg.lua.sed \ | sed "s/{{ domain }}/$domain/g" \ | sudo tee $domain.cfg.lua @@ -51,6 +56,22 @@ for domain in $(sudo yunohost domain list --raw); do fi done +# Remove old domains files +for file in /etc/metronome/conf.d/*; do + domain=$(echo $file \ + | sed 's|/etc/metronome/conf.d/||' \ + | sed 's|.cfg.lua||') + sanitzed_domain="$(echo $domain | sed 's/\./%2e/g')" + [[ $domain_list =~ $domain ]] \ + || $(sudo yunohost service saferemove -s metronome $file) == "True" \ + && rm -rf /var/lib/metronome/$sanitzed_domain + +done + +# Create domain directory +sudo chown -R metronome: /var/lib/metronome/ +sudo chown -R metronome: /etc/metronome/conf.d/ + # Restart if need be if [[ "$need_restart" == "True" ]]; then sudo service metronome restart diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 37f976ed..c28895f5 100644 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -49,6 +49,16 @@ for domain in $(sudo yunohost domain list --raw); do fi done +# Remove old domains files +for file in /etc/nginx/conf.d/*.*.conf; do + domain=$(echo $file \ + | sed 's|/etc/nginx/conf.d/||' \ + | sed 's|.conf||') + [[ $domain_list =~ $domain ]] \ + || $(sudo yunohost service saferemove -s nginx $file) == "True" \ + && (rm -r /etc/nginx/conf.d/$domain.d || true) +done + # Restart if need be if [[ "$need_restart" == "True" ]]; then sudo service nginx restart diff --git a/data/hooks/conf_regen/43-dnsmasq b/data/hooks/conf_regen/43-dnsmasq index 994566cc..d3271252 100644 --- a/data/hooks/conf_regen/43-dnsmasq +++ b/data/hooks/conf_regen/43-dnsmasq @@ -38,4 +38,11 @@ for domain in $(sudo yunohost domain list --raw); do safe_copy $domain /etc/dnsmasq.d/$domain done +# Remove old domains files +for file in /etc/dnsmasq.d/*.*; do + domain=$(echo $file | sed 's|/etc/dnsmasq.d/||') + [[ $domain_list =~ $domain ]] \ + || sudo yunohost service saferemove -s dnsmasq $file +done + sudo service dnsmasq reload From b615bcb810f3583b444975d42ce377539c2bd051 Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 19:04:19 -0400 Subject: [PATCH 56/86] [enh] Use the regenconf function instead of legacy configuration forging --- lib/yunohost/domain.py | 92 +++++------------------------------------- 1 file changed, 11 insertions(+), 81 deletions(-) diff --git a/lib/yunohost/domain.py b/lib/yunohost/domain.py index 2463e977..434e97e4 100644 --- a/lib/yunohost/domain.py +++ b/lib/yunohost/domain.py @@ -79,6 +79,8 @@ def domain_add(auth, domain, dyndns=False): dyndns -- Subscribe to DynDNS """ + from yunohost.service import service_regenconf + attr_dict = { 'objectClass' : ['mailDomain', 'top'] } try: ip = str(urlopen('http://ip.yunohost.org').read()) @@ -154,75 +156,12 @@ def domain_add(auth, domain, dyndns=False): attr_dict['virtualdomain'] = domain - dnsmasq_config_path='/etc/dnsmasq.d' - try: - os.listdir(dnsmasq_config_path) - except OSError: - msignals.display(m18n.n('dnsmasq_isnt_installed'), - 'warning') - os.makedirs(dnsmasq_config_path) - - try: - with open('%s/%s' % (dnsmasq_config_path, domain)) as f: pass - except IOError as e: - zone_lines = [ - 'resolv-file=', - 'address=/%s/%s' % (domain, ip), - 'txt-record=%s,"v=spf1 mx a -all"' % domain, - 'mx-host=%s,%s,5' % (domain, domain), - 'srv-host=_xmpp-client._tcp.%s,%s,5222,0,5' % (domain, domain), - 'srv-host=_xmpp-server._tcp.%s,%s,5269,0,5' % (domain, domain), - 'srv-host=_jabber._tcp.%s,%s,5269,0,5' % (domain, domain), - ] - with open('%s/%s' % (dnsmasq_config_path, domain), 'w') as zone: - for line in zone_lines: - zone.write(line + '\n') - os.system('service dnsmasq restart') - - else: - msignals.display(m18n.n('domain_zone_exists'), - 'warning') - - # XMPP - try: - with open('/etc/metronome/conf.d/%s.cfg.lua' % domain) as f: pass - except IOError as e: - conf_lines = [ - 'VirtualHost "%s"' % domain, - ' ssl = {', - ' key = "%s/key.pem";' % ssl_domain_path, - ' certificate = "%s/crt.pem";' % ssl_domain_path, - ' }', - ' authentication = "ldap2"', - ' ldap = {', - ' hostname = "localhost",', - ' user = {', - ' basedn = "ou=users,dc=yunohost,dc=org",', - ' filter = "(&(objectClass=posixAccount)(mail=*@%s))",' % domain, - ' usernamefield = "mail",', - ' namefield = "cn",', - ' },', - ' }', - ] - with open('/etc/metronome/conf.d/%s.cfg.lua' % domain, 'w') as conf: - for line in conf_lines: - conf.write(line + '\n') - - os.system('mkdir -p /var/lib/metronome/%s/pep' % domain.replace('.', '%2e')) - os.system('chown -R metronome: /var/lib/metronome/') - os.system('chown -R metronome: /etc/metronome/conf.d/') - os.system('service metronome restart') - - - # Nginx - os.system('cp /usr/share/yunohost/yunohost-config/nginx/template.conf /etc/nginx/conf.d/%s.conf' % domain) - os.system('mkdir /etc/nginx/conf.d/%s.d/' % domain) - os.system('sed -i s/yunohost.org/%s/g /etc/nginx/conf.d/%s.conf' % (domain, domain)) - os.system('service nginx reload') - if not auth.add('virtualdomain=%s,ou=domains' % domain, attr_dict): raise MoulinetteError(errno.EIO, m18n.n('domain_creation_failed')) + service_regenconf(service='nginx') + service_regenconf(service='metronome') + service_regenconf(service='dnsmasq') os.system('yunohost app ssowatconf > /dev/null 2>&1') except: # Force domain removal silently @@ -242,6 +181,8 @@ def domain_remove(auth, domain, force=False): force -- Force the domain removal """ + from yunohost.service import service_regenconf + if not force and domain not in domain_list(auth)['domains']: raise MoulinetteError(errno.EINVAL, m18n.n('domain_unknown')) @@ -258,24 +199,13 @@ def domain_remove(auth, domain, force=False): m18n.n('domain_uninstall_app_first')) if auth.remove('virtualdomain=' + domain + ',ou=domains') or force: - command_list = [ - 'rm -rf /etc/yunohost/certs/%s' % domain, - 'rm -f /etc/dnsmasq.d/%s' % domain, - 'rm -rf /var/lib/metronome/%s' % domain.replace('.', '%2e'), - 'rm -f /etc/metronome/conf.d/%s.cfg.lua' % domain, - 'rm -rf /etc/nginx/conf.d/%s.d' % domain, - 'rm -f /etc/nginx/conf.d/%s.conf' % domain, - ] - for command in command_list: - if os.system(command) != 0: - msignals.display(m18n.n('path_removal_failed', command[7:]), - 'warning') + os.system('rm -rf /etc/yunohost/certs/%s' % domain) else: raise MoulinetteError(errno.EIO, m18n.n('domain_deletion_failed')) + service_regenconf(service='nginx') + service_regenconf(service='metronome') + service_regenconf(service='dnsmasq') os.system('yunohost app ssowatconf > /dev/null 2>&1') - os.system('service nginx reload') - os.system('service dnsmasq restart') - os.system('service metronome restart') msignals.display(m18n.n('domain_deleted'), 'success') From 15533c7c6f55eeabdcf9fec9462c7d044cc3fcb9 Mon Sep 17 00:00:00 2001 From: kload Date: Wed, 30 Sep 2015 19:36:55 -0400 Subject: [PATCH 57/86] [fix] Various fixes on configuration regeneration --- data/actionsmap/yunohost.yml | 2 ++ data/hooks/conf_regen/12-metronome | 4 ++-- data/hooks/conf_regen/15-nginx | 7 ++++--- data/hooks/conf_regen/43-dnsmasq | 4 +++- lib/yunohost/service.py | 5 ----- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index 371ecf26..f90c3675 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -264,6 +264,7 @@ domain: action_help: Create a custom domain api: POST /domains configuration: + lock: false authenticate: all arguments: domain: @@ -282,6 +283,7 @@ domain: action_help: Delete domains api: DELETE /domains/ configuration: + lock: false authenticate: all arguments: domain: diff --git a/data/hooks/conf_regen/12-metronome b/data/hooks/conf_regen/12-metronome index d43660c5..b61e3832 100644 --- a/data/hooks/conf_regen/12-metronome +++ b/data/hooks/conf_regen/12-metronome @@ -63,8 +63,8 @@ for file in /etc/metronome/conf.d/*; do | sed 's|.cfg.lua||') sanitzed_domain="$(echo $domain | sed 's/\./%2e/g')" [[ $domain_list =~ $domain ]] \ - || $(sudo yunohost service saferemove -s metronome $file) == "True" \ - && rm -rf /var/lib/metronome/$sanitzed_domain + || ($(sudo yunohost service saferemove -s metronome $file) == "True" \ + && rm -rf /var/lib/metronome/$sanitzed_domain) done diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index c28895f5..7640e817 100644 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -37,9 +37,10 @@ safe_copy yunohost_local.conf \ need_restart=False +domain_list=$(sudo yunohost domain list --raw) # Copy a configuration file for each YunoHost domain -for domain in $(sudo yunohost domain list --raw); do +for domain in $domain_list; do sudo mkdir -p /etc/nginx/conf.d/$domain.d cat server.conf.sed \ | sed "s/{{ domain }}/$domain/g" \ @@ -55,8 +56,8 @@ for file in /etc/nginx/conf.d/*.*.conf; do | sed 's|/etc/nginx/conf.d/||' \ | sed 's|.conf||') [[ $domain_list =~ $domain ]] \ - || $(sudo yunohost service saferemove -s nginx $file) == "True" \ - && (rm -r /etc/nginx/conf.d/$domain.d || true) + || ($(sudo yunohost service saferemove -s nginx $file) == "True" \ + && (rm -r /etc/nginx/conf.d/$domain.d || true)) done # Restart if need be diff --git a/data/hooks/conf_regen/43-dnsmasq b/data/hooks/conf_regen/43-dnsmasq index d3271252..5c3c31aa 100644 --- a/data/hooks/conf_regen/43-dnsmasq +++ b/data/hooks/conf_regen/43-dnsmasq @@ -24,8 +24,10 @@ ipv6=$(ip route get 2000:: | grep -q "unreachable" && echo '' \ sudo mkdir -p /etc/dnsmasq.d +domain_list=$(sudo yunohost domain list --raw) + # Copy a configuration file for each YunoHost domain -for domain in $(sudo yunohost domain list --raw); do +for domain in $domain_list; do cat domain.sed \ | sed "s/{{ domain }}/$domain/g" \ | sed "s/{{ ip }}/$ip/g" \ diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 000f18ef..aa1f9d3e 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -466,11 +466,6 @@ def service_saferemove(service, conf_file, force=False): deleted = True msignals.display(m18n.n('service_configuration_backup', conf_backup_file), 'info') - elif keep: - services[service]['conffiles'][conf_file] = \ - previous_hash[0:32] + ', but keep ' + current_hash - msignals.display(m18n.n('service_configuration_backup', conf_backup_file), - 'info') else: services[service]['conffiles'][conf_file] = previous_hash os.remove(conf_backup_file) From 25f540ed02ad32594dae02bedf6d559264fcc615 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 14:32:40 -0400 Subject: [PATCH 58/86] [fix] Add missing services --- data/other/services.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data/other/services.yml b/data/other/services.yml index c183be54..c015c8cd 100644 --- a/data/other/services.yml +++ b/data/other/services.yml @@ -39,3 +39,13 @@ postgrey: amavis: status: service log: /var/log/mail.log +nslcd: + status: service + log: /var/log/syslog +nsswitch: + status: service +spamassassin: + status: service + log: /var/log/mail.log +udisks-glue: + status: service From cf84a91849c3bcdb4c429fb16b65d8d92de2ef37 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 14:36:29 -0400 Subject: [PATCH 59/86] [enh] Add SSL, nsswitch and udisks-glue regen conf scripts --- data/hooks/conf_regen/02-ssl | 50 ++++ data/hooks/conf_regen/46-nsswitch | 20 ++ data/hooks/conf_regen/49-udisks-glue | 20 ++ data/templates/nsswitch/nsswitch.conf | 21 ++ data/templates/ssl/openssl.cnf | 293 ++++++++++++++++++++ data/templates/udisks-glue/udisks-glue.conf | 9 + 6 files changed, 413 insertions(+) create mode 100644 data/hooks/conf_regen/02-ssl create mode 100644 data/hooks/conf_regen/46-nsswitch create mode 100644 data/hooks/conf_regen/49-udisks-glue create mode 100644 data/templates/nsswitch/nsswitch.conf create mode 100644 data/templates/ssl/openssl.cnf create mode 100644 data/templates/udisks-glue/udisks-glue.conf diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl new file mode 100644 index 00000000..2087978d --- /dev/null +++ b/data/hooks/conf_regen/02-ssl @@ -0,0 +1,50 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [ $force ]; then + sudo yunohost service safecopy \ + -s ssl $1 $2 --force + else + sudo yunohost service safecopy \ + -s ssl $1 $2 + fi +} + +cd /usr/share/yunohost/templates/ssl +ssl_dir=/usr/share/yunohost/yunohost-config/ssl/yunoCA + +sudo mkdir -p /etc/yunohost/certs/yunohost.org +sudo mkdir -p $ssl_dir/{ca,certs,crl,newcerts} + +if [ ! -f $ssl_dir/serial ]; then + echo "01" | sudo tee $ssl_dir/serial +fi + +if [ ! -f /etc/yunohost/current_host ]; then + echo "yunohost.org" | sudo tee /etc/yunohost/current_host +fi + +if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then + sudo openssl req -new -config $ssl_dir/openssl.cnf \ + -days 730 -out $ssl_dir/certs/yunohost_csr.pem \ + -keyout $ssl_dir/certs/yunohost_key.pem -nodes -batch + sudo openssl ca -config $ssl_dir/openssl.cnf \ + -days 730 -in $ssl_dir/certs/yunohost_csr.pem \ + -out $ssl_dir/certs/yunohost_crt.pem -batch + sudo cp $ssl_dir/ca/cacert.pem \ + /etc/yunohost/certs/yunohost.org/ca.pem + sudo cp $ssl_dir/certs/yunohost_key.pem \ + /etc/yunohost/certs/yunohost.org/key.pem + sudo cp $ssl_dir/yunoCA/newcerts/01.pem \ + /etc/yunohost/certs/yunohost.org/crt.pem + sudo ln -s /etc/yunohost/certs/yunohost.org/crt.pem \ + /etc/ssl/certs/yunohost_crt.pem + sudo ln -s /etc/yunohost/certs/yunohost.org/key.pem \ + /etc/ssl/private/yunohost_key.pem + sudo ln -s /etc/yunohost/certs/yunohost.org/ca.pem \ + /etc/ssl/certs/ca-yunohost_crt.pem + sudo update-ca-certificates +fi diff --git a/data/hooks/conf_regen/46-nsswitch b/data/hooks/conf_regen/46-nsswitch new file mode 100644 index 00000000..73535eed --- /dev/null +++ b/data/hooks/conf_regen/46-nsswitch @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s nsswitch $1 $2 --force + else + sudo yunohost service safecopy \ + -s nsswitch $1 $2 + fi +} + +cd /usr/share/yunohost/templates/nsswitch + +if [[ "$(safe_copy nsswitch.conf /etc/nsswitch.conf)" == "True" ]]; then + sudo service nscd restart +fi diff --git a/data/hooks/conf_regen/49-udisks-glue b/data/hooks/conf_regen/49-udisks-glue new file mode 100644 index 00000000..85de9182 --- /dev/null +++ b/data/hooks/conf_regen/49-udisks-glue @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s udisks-glue $1 $2 --force + else + sudo yunohost service safecopy \ + -s udisks-glue $1 $2 + fi +} + +cd /usr/share/yunohost/templates/udisks-glue + +if [[ "$(safe_copy udisks-glue.conf /etc/udisks-glue.conf)" == "True" ]]; then + sudo service udisks-glue restart +fi diff --git a/data/templates/nsswitch/nsswitch.conf b/data/templates/nsswitch/nsswitch.conf new file mode 100644 index 00000000..cf5b4525 --- /dev/null +++ b/data/templates/nsswitch/nsswitch.conf @@ -0,0 +1,21 @@ +# /etc/nsswitch.conf +# +# Example configuration of GNU Name Service Switch functionality. +# If you have the `glibc-doc-reference' and `info' packages installed, try: +# `info libc "Name Service Switch"' for information about this file. + +passwd: compat ldap +group: compat ldap +shadow: compat ldap +gshadow: files + +hosts: files mdns4_minimal [NOTFOUND=return] dns +networks: files + +protocols: db files +services: db files +ethers: db files +rpc: db files + +netgroup: nis +sudoers: files ldap diff --git a/data/templates/ssl/openssl.cnf b/data/templates/ssl/openssl.cnf new file mode 100644 index 00000000..fa5d19fa --- /dev/null +++ b/data/templates/ssl/openssl.cnf @@ -0,0 +1,293 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = /usr/share/yunohost/yunohost-config/ssl +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = Yunohost # The default ca section + +#################################################################### +[ Yunohost ] + +dir = /usr/share/yunohost/yunohost-config/ssl/yunoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +unique_subject = no # Set to 'no' to allow creation of + # several ctificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/ca/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +#crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/ca/cakey.pem # The private key +RANDFILE = $dir/ca/.rand # private random number file + +x509_extensions = usr_cert # The extentions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 3650 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha256 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = optional +stateOrProvinceName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 2048 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extentions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +commonName = Common Name (eg, YOUR name) +commonName_max = 64 +commonName_default = yunohost.org + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +subjectAltName=DNS:yunohost.org,DNS:www.yunohost.org,DNS:ns.yunohost.org + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/data/templates/udisks-glue/udisks-glue.conf b/data/templates/udisks-glue/udisks-glue.conf new file mode 100644 index 00000000..f97de948 --- /dev/null +++ b/data/templates/udisks-glue/udisks-glue.conf @@ -0,0 +1,9 @@ +filter disks { + optical = false + partition_table = false + usage = filesystem +} +match disks { + automount=true + automount_options= { sync, noatime, "dmask=0", "fmask=0" } +} From 0ed2081f89813d8b7f11f806df3b94f72fdde60a Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 16:36:30 -0400 Subject: [PATCH 60/86] [enh] Make postinstall and main domain change regen-conf friendly --- data/hooks/conf_regen/01-yunohost | 22 + data/hooks/conf_regen/15-nginx | 89 +-- data/hooks/conf_regen/52-fail2ban | 29 + data/templates/fail2ban/jail-jessie.conf | 584 ++++++++++++++++++ .../fail2ban/{jail.conf => jail-wheezy.conf} | 2 + .../yunohost}/firewall.yml | 0 .../yunohost}/services.yml | 0 debian/install | 1 + debian/postinst | 56 +- lib/yunohost/tools.py | 67 +- 10 files changed, 701 insertions(+), 149 deletions(-) create mode 100644 data/hooks/conf_regen/01-yunohost create mode 100644 data/hooks/conf_regen/52-fail2ban create mode 100644 data/templates/fail2ban/jail-jessie.conf rename data/templates/fail2ban/{jail.conf => jail-wheezy.conf} (99%) rename data/{other => templates/yunohost}/firewall.yml (100%) rename data/{other => templates/yunohost}/services.yml (100%) diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost new file mode 100644 index 00000000..5ff8e8da --- /dev/null +++ b/data/hooks/conf_regen/01-yunohost @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +force=$1 + +cd /usr/share/yunohost/templates/yunohost + +sudo mkdir -p /etc/yunohost + +if [ ! -f /etc/yunohost/firewall.yml ]; then + sudo cp firewall.yml /etc/yunohost/firewall.yml +fi + +if [ ! -f /etc/yunohost/services.yml ]; then + sudo cp services.yml /etc/yunohost/services.yml +fi + +# Allow users to access /media directory +if [ ! -d /etc/skel/media ]; then + mkdir -p /media + ln -s /media /etc/skel/ +fi diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 7640e817..9ef3724f 100644 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -4,15 +4,19 @@ set -e force=$1 function safe_copy () { - if [[ "$force" == "True" ]]; then - sudo yunohost service safecopy \ - -s nginx \ - $1 $2 \ - --force + if [ ! -f /etc/yunohost/installed ]; then + sudo cp $1 $2 else - sudo yunohost service safecopy \ - -s nginx \ - $1 $2 + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s nginx \ + $1 $2 \ + --force + else + sudo yunohost service safecopy \ + -s nginx \ + $1 $2 + fi fi } @@ -30,39 +34,48 @@ for file in $files; do done -# Copy 'yunohost.local' to the main domain conf directory -main_domain=$(cat /etc/yunohost/current_host) -safe_copy yunohost_local.conf \ - /etc/nginx/conf.d/$main_domain.d/yunohost_local.conf +if [ -f /etc/yunohost/installed ]; then + + # Copy 'yunohost.local' to the main domain conf directory + main_domain=$(cat /etc/yunohost/current_host) + safe_copy yunohost_local.conf \ + /etc/nginx/conf.d/$main_domain.d/yunohost_local.conf -need_restart=False -domain_list=$(sudo yunohost domain list --raw) + need_restart=False + domain_list=$(sudo yunohost domain list --raw) -# Copy a configuration file for each YunoHost domain -for domain in $domain_list; do - sudo mkdir -p /etc/nginx/conf.d/$domain.d - cat server.conf.sed \ - | sed "s/{{ domain }}/$domain/g" \ - | sudo tee $domain.conf - if [[ $(safe_copy $domain.conf /etc/nginx/conf.d/$domain.conf) == "True" ]]; then - need_restart=True - fi -done + # Copy a configuration file for each YunoHost domain + for domain in $domain_list; do + sudo mkdir -p /etc/nginx/conf.d/$domain.d + cat server.conf.sed \ + | sed "s/{{ domain }}/$domain/g" \ + | sudo tee $domain.conf + [[ $(safe_copy $domain.conf /etc/nginx/conf.d/$domain.conf) == "True" ]] \ + && need_restart=True -# Remove old domains files -for file in /etc/nginx/conf.d/*.*.conf; do - domain=$(echo $file \ - | sed 's|/etc/nginx/conf.d/||' \ - | sed 's|.conf||') - [[ $domain_list =~ $domain ]] \ - || ($(sudo yunohost service saferemove -s nginx $file) == "True" \ - && (rm -r /etc/nginx/conf.d/$domain.d || true)) -done + [ -f /etc/nginx/conf.d/$domain.d/yunohost_local.conf ] \ + && [[ $main_domain != $domain ]] \ + && sudo yunohost service saferemove -s nginx \ + /etc/nginx/conf.d/$domain.d/yunohost_local.conf + done + + + # Remove old domains files + for file in /etc/nginx/conf.d/*.*.conf; do + domain=$(echo $file \ + | sed 's|/etc/nginx/conf.d/||' \ + | sed 's|.conf||') + [[ $domain_list =~ $domain ]] \ + || ($(sudo yunohost service saferemove -s nginx $file) == "True" \ + && (rm -r /etc/nginx/conf.d/$domain.d || true)) + done + +else + need_restart=True +fi # Restart if need be -if [[ "$need_restart" == "True" ]]; then - sudo service nginx restart -else - sudo service nginx reload -fi +[[ "$need_restart" == "True" ]] \ + && sudo service nginx restart \ + || sudo service nginx reload diff --git a/data/hooks/conf_regen/52-fail2ban b/data/hooks/conf_regen/52-fail2ban new file mode 100644 index 00000000..9c609c74 --- /dev/null +++ b/data/hooks/conf_regen/52-fail2ban @@ -0,0 +1,29 @@ +#!/bin/bash +set -e + +force=$1 + +function safe_copy () { + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s fail2ban $1 $2 --force + else + sudo yunohost service safecopy \ + -s fail2ban $1 $2 + fi +} + +cd /usr/share/yunohost/templates/fail2ban + +sudo mkdir -p /etc/fail2ban/filter.d +safe_copy yunohost.conf /etc/fail2ban/filter.d/yunohost.conf + +# Compatibility: change from HDB to MDB on Jessie +version=$(sed 's/\..*//' /etc/debian_version) +[[ "$version" == '8' ]] \ + && sudo cp jail-jessie.conf jail.conf \ + || sudo cp jail-wheezy.conf jail.conf + +if [[ $(safe_copy jail.conf /etc/fail2ban/jail.conf) == "True" ]]; then + sudo service fail2ban restart +fi diff --git a/data/templates/fail2ban/jail-jessie.conf b/data/templates/fail2ban/jail-jessie.conf new file mode 100644 index 00000000..59dcf51d --- /dev/null +++ b/data/templates/fail2ban/jail-jessie.conf @@ -0,0 +1,584 @@ +# Fail2Ban configuration file. +# +# This file was composed for Debian systems from the original one +# provided now under /usr/share/doc/fail2ban/examples/jail.conf +# for additional examples. +# +# Comments: use '#' for comment lines and ';' for inline comments +# +# To avoid merges during upgrades DO NOT MODIFY THIS FILE +# and rather provide your changes in /etc/fail2ban/jail.local +# + +# The DEFAULT allows a global definition of the options. They can be overridden +# in each jail afterwards. + +[DEFAULT] + +# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not +# ban a host which matches an address in this list. Several addresses can be +# defined using space separator. +ignoreip = 127.0.0.1/8 + +# External command that will take an tagged arguments to ignore, e.g. , +# and return true if the IP is to be ignored. False otherwise. +# +# ignorecommand = /path/to/command +ignorecommand = + +# "bantime" is the number of seconds that a host is banned. +bantime = 600 + +# A host is banned if it has generated "maxretry" during the last "findtime" +# seconds. +findtime = 600 +maxretry = 3 + +# "backend" specifies the backend used to get files modification. +# Available options are "pyinotify", "gamin", "polling" and "auto". +# This option can be overridden in each jail as well. +# +# pyinotify: requires pyinotify (a file alteration monitor) to be installed. +# If pyinotify is not installed, Fail2ban will use auto. +# gamin: requires Gamin (a file alteration monitor) to be installed. +# If Gamin is not installed, Fail2ban will use auto. +# polling: uses a polling algorithm which does not require external libraries. +# auto: will try to use the following backends, in order: +# pyinotify, gamin, polling. +backend = auto + +# "usedns" specifies if jails should trust hostnames in logs, +# warn when reverse DNS lookups are performed, or ignore all hostnames in logs +# +# yes: if a hostname is encountered, a reverse DNS lookup will be performed. +# warn: if a hostname is encountered, a reverse DNS lookup will be performed, +# but it will be logged as a warning. +# no: if a hostname is encountered, will not be used for banning, +# but it will be logged as info. +usedns = warn + +# +# Destination email address used solely for the interpolations in +# jail.{conf,local} configuration files. +destemail = root@localhost + +# +# Name of the sender for mta actions +sendername = Fail2Ban + +# Email address of the sender +sender = fail2ban@localhost + +# +# ACTIONS +# + +# Default banning action (e.g. iptables, iptables-new, +# iptables-multiport, shorewall, etc) It is used to define +# action_* variables. Can be overridden globally or per +# section within jail.local file +banaction = iptables-multiport + +# email action. Since 0.8.1 upstream fail2ban uses sendmail +# MTA for the mailing. Change mta configuration parameter to mail +# if you want to revert to conventional 'mail'. +mta = sendmail + +# Default protocol +protocol = tcp + +# Specify chain where jumps would need to be added in iptables-* actions +chain = INPUT + +# +# Action shortcuts. To be used to define action parameter + +# The simplest action to take: ban only +action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + +# ban & send an e-mail with whois report to the destemail. +action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s", sendername="%(sendername)s"] + +# ban & send an e-mail with whois report and relevant log lines +# to the destemail. +action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"] + +# Choose default action. To change, just override value of 'action' with the +# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local +# globally (section [DEFAULT]) or per specific section +action = %(action_)s + +# +# JAILS +# + +# Next jails corresponds to the standard configuration in Fail2ban 0.6 which +# was shipped in Debian. Enable any defined here jail by including +# +# [SECTION_NAME] +# enabled = true + +# +# in /etc/fail2ban/jail.local. +# +# Optionally you may override any other parameter (e.g. banaction, +# action, port, logpath, etc) in that section within jail.local + +[ssh] + +enabled = true +port = ssh +filter = sshd +logpath = /var/log/auth.log +maxretry = 6 + +[dropbear] + +enabled = false +port = ssh +filter = dropbear +logpath = /var/log/auth.log +maxretry = 6 + +# Generic filter for pam. Has to be used with action which bans all ports +# such as iptables-allports, shorewall +[pam-generic] + +enabled = true +# pam-generic filter can be customized to monitor specific subset of 'tty's +filter = pam-generic +# port actually must be irrelevant but lets leave it all for some possible uses +port = all +banaction = iptables-allports +port = anyport +logpath = /var/log/auth.log +maxretry = 6 + +[xinetd-fail] + +enabled = false +filter = xinetd-fail +port = all +banaction = iptables-multiport-log +logpath = /var/log/daemon.log +maxretry = 2 + + +[ssh-ddos] + +enabled = false +port = ssh +filter = sshd-ddos +logpath = /var/log/auth.log +maxretry = 6 + + +# Here we use blackhole routes for not requiring any additional kernel support +# to store large volumes of banned IPs + +[ssh-route] + +enabled = false +filter = sshd +action = route +logpath = /var/log/sshd.log +maxretry = 6 + +# Here we use a combination of Netfilter/Iptables and IPsets +# for storing large volumes of banned IPs +# +# IPset comes in two versions. See ipset -V for which one to use +# requires the ipset package and kernel support. +[ssh-iptables-ipset4] + +enabled = false +port = ssh +filter = sshd +banaction = iptables-ipset-proto4 +logpath = /var/log/sshd.log +maxretry = 6 + +[ssh-iptables-ipset6] + +enabled = false +port = ssh +filter = sshd +banaction = iptables-ipset-proto6 +logpath = /var/log/sshd.log +maxretry = 6 + + +# +# HTTP servers +# + +[apache] + +enabled = false +port = http,https +filter = apache-auth +logpath = /var/log/apache*/*error.log +maxretry = 6 + +# default action is now multiport, so apache-multiport jail was left +# for compatibility with previous (<0.7.6-2) releases +[apache-multiport] + +enabled = false +port = http,https +filter = apache-auth +logpath = /var/log/apache*/*error.log +maxretry = 6 + +[apache-noscript] + +enabled = false +port = http,https +filter = apache-noscript +logpath = /var/log/apache*/*error.log +maxretry = 6 + +[apache-overflows] + +enabled = false +port = http,https +filter = apache-overflows +logpath = /var/log/apache*/*error.log +maxretry = 2 + +[apache-modsecurity] + +enabled = false +filter = apache-modsecurity +port = http,https +logpath = /var/log/apache*/*error.log +maxretry = 2 + +[apache-nohome] + +enabled = false +filter = apache-nohome +port = http,https +logpath = /var/log/apache*/*error.log +maxretry = 2 + +# Ban attackers that try to use PHP's URL-fopen() functionality +# through GET/POST variables. - Experimental, with more than a year +# of usage in production environments. + +[php-url-fopen] + +enabled = false +port = http,https +filter = php-url-fopen +logpath = /var/www/*/logs/access_log + +# A simple PHP-fastcgi jail which works with lighttpd. +# If you run a lighttpd server, then you probably will +# find these kinds of messages in your error_log: +# ALERT – tried to register forbidden variable ‘GLOBALS’ +# through GET variables (attacker '1.2.3.4', file '/var/www/default/htdocs/index.php') + +[lighttpd-fastcgi] + +enabled = false +port = http,https +filter = lighttpd-fastcgi +logpath = /var/log/lighttpd/error.log + +# Same as above for mod_auth +# It catches wrong authentifications + +[lighttpd-auth] + +enabled = false +port = http,https +filter = suhosin +logpath = /var/log/lighttpd/error.log + +[nginx-http-auth] + +enabled = false +filter = nginx-http-auth +port = http,https +logpath = /var/log/nginx/error.log + +# Monitor roundcube server + +[roundcube-auth] + +enabled = false +filter = roundcube-auth +port = http,https +logpath = /var/log/roundcube/userlogins + + +[sogo-auth] + +enabled = false +filter = sogo-auth +port = http, https +# without proxy this would be: +# port = 20000 +logpath = /var/log/sogo/sogo.log + + +# +# FTP servers +# + +[vsftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = vsftpd +logpath = /var/log/vsftpd.log +# or overwrite it in jails.local to be +# logpath = /var/log/auth.log +# if you want to rely on PAM failed login attempts +# vsftpd's failregex should match both of those formats +maxretry = 6 + + +[proftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = proftpd +logpath = /var/log/proftpd/proftpd.log +maxretry = 6 + + +[pure-ftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = pure-ftpd +logpath = /var/log/syslog +maxretry = 6 + + +[wuftpd] + +enabled = false +port = ftp,ftp-data,ftps,ftps-data +filter = wuftpd +logpath = /var/log/syslog +maxretry = 6 + + +# +# Mail servers +# + +[postfix] + +enabled = true +port = smtp,ssmtp,submission +filter = postfix +logpath = /var/log/mail.log + + +[couriersmtp] + +enabled = false +port = smtp,ssmtp,submission +filter = couriersmtp +logpath = /var/log/mail.log + + +# +# Mail servers authenticators: might be used for smtp,ftp,imap servers, so +# all relevant ports get banned +# + +[courierauth] + +enabled = false +port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s +filter = courierlogin +logpath = /var/log/mail.log + + +[sasl] + +enabled = true +port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s +filter = postfix-sasl +# You might consider monitoring /var/log/mail.warn instead if you are +# running postfix since it would provide the same log lines at the +# "warn" level but overall at the smaller filesize. +logpath = /var/log/mail.log + +[dovecot] + +enabled = true +port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s +filter = dovecot +logpath = /var/log/mail.log + +# To log wrong MySQL access attempts add to /etc/my.cnf: +# log-error=/var/log/mysqld.log +# log-warning = 2 +[mysqld-auth] + +enabled = false +filter = mysqld-auth +port = 3306 +logpath = /var/log/mysqld.log + + +# DNS Servers + + +# These jails block attacks against named (bind9). By default, logging is off +# with bind9 installation. You will need something like this: +# +# logging { +# channel security_file { +# file "/var/log/named/security.log" versions 3 size 30m; +# severity dynamic; +# print-time yes; +# }; +# category security { +# security_file; +# }; +# }; +# +# in your named.conf to provide proper logging + +# !!! WARNING !!! +# Since UDP is connection-less protocol, spoofing of IP and imitation +# of illegal actions is way too simple. Thus enabling of this filter +# might provide an easy way for implementing a DoS against a chosen +# victim. See +# http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html +# Please DO NOT USE this jail unless you know what you are doing. +#[named-refused-udp] +# +#enabled = false +#port = domain,953 +#protocol = udp +#filter = named-refused +#logpath = /var/log/named/security.log + +[named-refused-tcp] + +enabled = false +port = domain,953 +protocol = tcp +filter = named-refused +logpath = /var/log/named/security.log + +[freeswitch] + +enabled = false +filter = freeswitch +logpath = /var/log/freeswitch.log +maxretry = 10 +action = iptables-multiport[name=freeswitch-tcp, port="5060,5061,5080,5081", protocol=tcp] + iptables-multiport[name=freeswitch-udp, port="5060,5061,5080,5081", protocol=udp] + +[ejabberd-auth] + +enabled = false +filter = ejabberd-auth +port = xmpp-client +protocol = tcp +logpath = /var/log/ejabberd/ejabberd.log + + +# Multiple jails, 1 per protocol, are necessary ATM: +# see https://github.com/fail2ban/fail2ban/issues/37 +[asterisk-tcp] + +enabled = false +filter = asterisk +port = 5060,5061 +protocol = tcp +logpath = /var/log/asterisk/messages + +[asterisk-udp] + +enabled = false +filter = asterisk +port = 5060,5061 +protocol = udp +logpath = /var/log/asterisk/messages + + +# Jail for more extended banning of persistent abusers +# !!! WARNING !!! +# Make sure that your loglevel specified in fail2ban.conf/.local +# is not at DEBUG level -- which might then cause fail2ban to fall into +# an infinite loop constantly feeding itself with non-informative lines +[recidive] + +enabled = false +filter = recidive +logpath = /var/log/fail2ban.log +action = iptables-allports[name=recidive] + sendmail-whois-lines[name=recidive, logpath=/var/log/fail2ban.log] +bantime = 604800 ; 1 week +findtime = 86400 ; 1 day +maxretry = 5 + +# See the IMPORTANT note in action.d/blocklist_de.conf for when to +# use this action +# +# Report block via blocklist.de fail2ban reporting service API +# See action.d/blocklist_de.conf for more information +[ssh-blocklist] + +enabled = false +filter = sshd +action = iptables[name=SSH, port=ssh, protocol=tcp] + sendmail-whois[name=SSH, dest="%(destemail)s", sender="%(sender)s", sendername="%(sendername)s"] + blocklist_de[email="%(sender)s", apikey="xxxxxx", service="%(filter)s"] +logpath = /var/log/sshd.log +maxretry = 20 + + +# consider low maxretry and a long bantime +# nobody except your own Nagios server should ever probe nrpe +[nagios] +enabled = false +filter = nagios +action = iptables[name=Nagios, port=5666, protocol=tcp] + sendmail-whois[name=Nagios, dest="%(destemail)s", sender="%(sender)s", sendername="%(sendername)s"] +logpath = /var/log/messages ; nrpe.cfg may define a different log_facility +maxretry = 1 + +[nginx] + +enabled = true +port = http,https +filter = apache-auth +logpath = /var/log/nginx*/*error.log +maxretry = 6 + +[nginx-noscript] + +enabled = false +port = http,https +filter = apache-noscript +logpath = /var/log/nginx*/*error.log +maxretry = 6 + +[nginx-overflows] + +enabled = false +port = http,https +filter = apache-overflows +logpath = /var/log/nginx*/*error.log +maxretry = 4 + +[yunohost] + +enabled = true +port = http,https +protocol = tcp +filter = yunohost +logpath = /var/log/nginx/*.log diff --git a/data/templates/fail2ban/jail.conf b/data/templates/fail2ban/jail-wheezy.conf similarity index 99% rename from data/templates/fail2ban/jail.conf rename to data/templates/fail2ban/jail-wheezy.conf index c1cde026..8eb0e7a1 100644 --- a/data/templates/fail2ban/jail.conf +++ b/data/templates/fail2ban/jail-wheezy.conf @@ -231,6 +231,8 @@ port = smtp,ssmtp filter = postfix logpath = /var/log/mail.log +[couriersmtp] + enabled = false port = smtp,ssmtp filter = couriersmtp diff --git a/data/other/firewall.yml b/data/templates/yunohost/firewall.yml similarity index 100% rename from data/other/firewall.yml rename to data/templates/yunohost/firewall.yml diff --git a/data/other/services.yml b/data/templates/yunohost/services.yml similarity index 100% rename from data/other/services.yml rename to data/templates/yunohost/services.yml diff --git a/debian/install b/debian/install index 4c91fbd4..772027be 100644 --- a/debian/install +++ b/debian/install @@ -2,6 +2,7 @@ bin/* /usr/bin/ data/actionsmap/* /usr/share/moulinette/actionsmap/ data/hooks/* /usr/share/yunohost/hooks/ data/other/* /usr/share/yunohost/yunohost-config/moulinette/ +data/templates/* /usr/share/yunohost/templates/ data/apps/* /usr/share/yunohost/apps/ lib/yunohost/*.py /usr/lib/moulinette/yunohost/ locales/* /usr/lib/moulinette/yunohost/locales/ diff --git a/debian/postinst b/debian/postinst index 3106cfed..ec92de4d 100644 --- a/debian/postinst +++ b/debian/postinst @@ -3,62 +3,12 @@ set -e do_configure() { - TMP=/usr/share/yunohost/yunohost-config/moulinette - - if [ ! -d /etc/yunohost ]; - then - mkdir -p /etc/yunohost - fi - - # Allow users to access /media directory - if [ ! -d /etc/skel/media ]; - then - mkdir -p /media - ln -s /media /etc/skel/ - fi - - #Firewall - grep -q "UPNP:" /etc/yunohost/firewall.yml > /dev/null 2>&1 - if [[ $? -eq 0 ]] || [ ! -f /etc/yunohost/firewall.yml ]; - then - cp $TMP/firewall.yml /etc/yunohost/ - fi - - # App fetchlist - if [ -f /etc/cron.d/yunohost-applist-yunohost ]; - then - sed -i "s/--no-ldap //g" /etc/cron.d/yunohost-applist-yunohost - fi - - # Service list - if [ ! -f /etc/yunohost/services.yml ]; - then - cp $TMP/services.yml /etc/yunohost/ - fi - - # Stop old API - ps aux | grep "yunohost.tac" | grep -qv grep - if [[ $? -eq 0 ]]; - then - killall twistd - fi - rm -rf /var/cache/moulinette/* - update-rc.d yunohost-api defaults > /dev/null service yunohost-api restart - # Firewall - update-rc.d yunohost-firewall defaults > /dev/null - - # Reload SSOwat conf if obsolete - if [ -f /etc/yunohost/installed ]; - then - yunohost firewall upnp | grep -qi "true" - if [[ $? -eq 0 ]]; - then - yunohost firewall upnp enable - fi - yunohost app ssowatconf + if [ ! -f /etc/yunohost/installed ]; then + bash /usr/share/yunohost/hooks/conf_regen/02-ssl + bash /usr/share/yunohost/hooks/conf_regen/15-nginx fi } diff --git a/lib/yunohost/tools.py b/lib/yunohost/tools.py index 95fbe8f8..ca31e641 100644 --- a/lib/yunohost/tools.py +++ b/lib/yunohost/tools.py @@ -106,6 +106,7 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False): """ from yunohost.domain import domain_add, domain_list from yunohost.dyndns import dyndns_subscribe + from yunohost.service import service_regenconf if not old_domain: with open('/etc/yunohost/current_host', 'r') as f: @@ -119,71 +120,13 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False): if new_domain not in domain_list(auth)['domains']: domain_add(auth, new_domain) - config_files = [ - '/etc/postfix/main.cf', - '/etc/metronome/metronome.cfg.lua', - '/etc/dovecot/dovecot.conf', - '/usr/share/yunohost/yunohost-config/others/startup', - '/etc/amavis/conf.d/05-node_id', - '/etc/amavis/conf.d/50-user' - ] - - config_dir = [] - - for dir in config_dir: - for file in os.listdir(dir): - config_files.append(dir + '/' + file) - - for file in config_files: - with open(file, "r") as sources: - lines = sources.readlines() - with open(file, "w") as sources: - for line in lines: - sources.write(re.sub(r''+ old_domain +'', new_domain, line)) - - ## Update DNS zone file for old and new domains - main_subdomains = ['pubsub', 'muc', 'vjud'] - try: - with open('/var/lib/bind/%s.zone' % old_domain, 'r') as f: - old_zone = f.read() - except IOError: - pass - else: - # Remove unneeded subdomains entries - for sub in main_subdomains: - old_zone = re.sub( - r'^({sub}.{domain}.|{sub})[\ \t]+(IN).*$[\n]?'.format( - sub=sub, domain=old_domain), - '', old_zone, 1, re.MULTILINE) - with open('/var/lib/bind/%s.zone' % old_domain, 'w') as f: - f.write(old_zone) - try: - with open('/var/lib/bind/%s.zone' % new_domain, 'r') as f: - new_zone = f.read() - except IOError: - msignals.display(m18n.n('domain_zone_not_found', new_domain), 'warning') - else: - # Add main subdomains entries - for sub in main_subdomains: - new_zone += '{sub} IN CNAME {domain}.\n'.format( - sub=sub, domain=new_domain) - with open('/var/lib/bind/%s.zone' % new_domain, 'w') as f: - f.write(new_zone) - os.system('rm /etc/ssl/private/yunohost_key.pem') os.system('rm /etc/ssl/certs/yunohost_crt.pem') command_list = [ - 'rm -f /etc/nginx/conf.d/%s.d/yunohost_local.conf' % old_domain, - 'cp /usr/share/yunohost/yunohost-config/nginx/yunohost_local.conf /etc/nginx/conf.d/%s.d/' % new_domain, 'ln -s /etc/yunohost/certs/%s/key.pem /etc/ssl/private/yunohost_key.pem' % new_domain, 'ln -s /etc/yunohost/certs/%s/crt.pem /etc/ssl/certs/yunohost_crt.pem' % new_domain, 'echo %s > /etc/yunohost/current_host' % new_domain, - 'service metronome restart', - 'service postfix restart', - 'service dovecot restart', - 'service amavis restart', - 'service nginx restart', ] for command in command_list: @@ -202,6 +145,11 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False): if dyndomain in dyndomains: dyndns_subscribe(domain=new_domain) + try: + with open('/etc/yunohost/installed', 'r') as f: + service_regenconf() + except IOError: pass + msignals.display(m18n.n('maindomain_changed'), 'success') @@ -219,6 +167,7 @@ def tools_postinstall(domain, password, ignore_dyndns=False): from yunohost.app import app_ssowatconf from yunohost.firewall import firewall_upnp, firewall_reload + from yunohost.service import service_regenconf dyndns = not ignore_dyndns @@ -327,6 +276,8 @@ def tools_postinstall(domain, password, ignore_dyndns=False): os.system('touch /etc/yunohost/installed') + service_regenconf() + msignals.display(m18n.n('yunohost_configured'), 'success') From 91ad01b839a0c84a2c2bb81a31467c977b097a73 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 16:38:22 -0400 Subject: [PATCH 61/86] [fix] Compatibility with the new moulinette '--plain' option --- data/hooks/conf_regen/12-metronome | 2 +- data/hooks/conf_regen/15-nginx | 2 +- data/hooks/conf_regen/43-dnsmasq | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/hooks/conf_regen/12-metronome b/data/hooks/conf_regen/12-metronome index b61e3832..70fa64dd 100644 --- a/data/hooks/conf_regen/12-metronome +++ b/data/hooks/conf_regen/12-metronome @@ -41,7 +41,7 @@ safe_copy metronome.logrotate /etc/logrotate.d/metronome need_restart=False sudo mkdir -p /etc/metronome/conf.d -domain_list=$(sudo yunohost domain list --raw) +domain_list=$(sudo yunohost domain list --plain) # Copy a configuration file for each YunoHost domain for domain in $domain_list; do diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 9ef3724f..a3754a45 100644 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -43,7 +43,7 @@ if [ -f /etc/yunohost/installed ]; then need_restart=False - domain_list=$(sudo yunohost domain list --raw) + domain_list=$(sudo yunohost domain list --plain) # Copy a configuration file for each YunoHost domain for domain in $domain_list; do diff --git a/data/hooks/conf_regen/43-dnsmasq b/data/hooks/conf_regen/43-dnsmasq index 5c3c31aa..821bfa39 100644 --- a/data/hooks/conf_regen/43-dnsmasq +++ b/data/hooks/conf_regen/43-dnsmasq @@ -24,7 +24,7 @@ ipv6=$(ip route get 2000:: | grep -q "unreachable" && echo '' \ sudo mkdir -p /etc/dnsmasq.d -domain_list=$(sudo yunohost domain list --raw) +domain_list=$(sudo yunohost domain list --plain) # Copy a configuration file for each YunoHost domain for domain in $domain_list; do From cc72a248939ec7ea9ffc9d6e3c3ebc087de13bf4 Mon Sep 17 00:00:00 2001 From: Le Kload Date: Thu, 1 Oct 2015 23:17:04 +0200 Subject: [PATCH 62/86] [fix] Do not use preinst script --- debian/preinst | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 debian/preinst diff --git a/debian/preinst b/debian/preinst deleted file mode 100644 index 43850db1..00000000 --- a/debian/preinst +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -set -e - -if [ -f /etc/init.d/yunohost-api ]; then - service yunohost-api stop -# nc -zv 127.0.0.1 6787 < /dev/null 2> /dev/null -# if [[ ! $? -eq 0 ]]; -# then -# exit 1 -# fi -fi From 21d1aa72d4cc1ac5b2408db5f73defe4cbe20116 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 17:20:52 -0400 Subject: [PATCH 63/86] [fix] Do copy the openssl configuration file --- data/hooks/conf_regen/02-ssl | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index 2087978d..0331b64c 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -4,12 +4,16 @@ set -e force=$1 function safe_copy () { - if [ $force ]; then - sudo yunohost service safecopy \ - -s ssl $1 $2 --force + if [ ! -f /etc/yunohost/installed ]; then + sudo cp $1 $2 else - sudo yunohost service safecopy \ - -s ssl $1 $2 + if [ $force ]; then + sudo yunohost service safecopy \ + -s ssl $1 $2 --force + else + sudo yunohost service safecopy \ + -s ssl $1 $2 + fi fi } @@ -19,6 +23,8 @@ ssl_dir=/usr/share/yunohost/yunohost-config/ssl/yunoCA sudo mkdir -p /etc/yunohost/certs/yunohost.org sudo mkdir -p $ssl_dir/{ca,certs,crl,newcerts} +safe_copy openssl.cnf $ssl_dir/openssl.cnf + if [ ! -f $ssl_dir/serial ]; then echo "01" | sudo tee $ssl_dir/serial fi From 6411d0e08eb1c32933ddeabf9d583607a140bb34 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 17:34:30 -0400 Subject: [PATCH 64/86] [fix] Run yunohost hook + create the CA at package installation --- data/hooks/conf_regen/01-yunohost | 4 ++++ data/hooks/conf_regen/02-ssl | 6 ++++-- debian/postinst | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost index 5ff8e8da..30d77a5d 100644 --- a/data/hooks/conf_regen/01-yunohost +++ b/data/hooks/conf_regen/01-yunohost @@ -7,6 +7,10 @@ cd /usr/share/yunohost/templates/yunohost sudo mkdir -p /etc/yunohost +if [ ! -f /etc/yunohost/current_host ]; then + echo "yunohost.org" | sudo tee /etc/yunohost/current_host +fi + if [ ! -f /etc/yunohost/firewall.yml ]; then sudo cp firewall.yml /etc/yunohost/firewall.yml fi diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index 0331b64c..c8812d1c 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -29,8 +29,10 @@ if [ ! -f $ssl_dir/serial ]; then echo "01" | sudo tee $ssl_dir/serial fi -if [ ! -f /etc/yunohost/current_host ]; then - echo "yunohost.org" | sudo tee /etc/yunohost/current_host +if [ ! -f /etc/yunohost/certs/yunohost.org/ca.pem ]; then + sudo openssl req -x509 -new -config $ssl_dir/openssl.cnf \ + -days 3650 -out $ssl_dir/ca/cacert.pem \ + -keyout $ssl_dir/ca/cakey.pem -nodes -batch fi if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then diff --git a/debian/postinst b/debian/postinst index ec92de4d..c1159dfd 100644 --- a/debian/postinst +++ b/debian/postinst @@ -7,6 +7,7 @@ do_configure() { service yunohost-api restart if [ ! -f /etc/yunohost/installed ]; then + bash /usr/share/yunohost/hooks/conf_regen/01-yunohost bash /usr/share/yunohost/hooks/conf_regen/02-ssl bash /usr/share/yunohost/hooks/conf_regen/15-nginx fi From 72e2cbeef98cb9c817362cec80bcac473d66350c Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 17:42:55 -0400 Subject: [PATCH 65/86] [fix] Typo --- data/hooks/conf_regen/02-ssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index c8812d1c..8c54be5e 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -46,7 +46,7 @@ if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then /etc/yunohost/certs/yunohost.org/ca.pem sudo cp $ssl_dir/certs/yunohost_key.pem \ /etc/yunohost/certs/yunohost.org/key.pem - sudo cp $ssl_dir/yunoCA/newcerts/01.pem \ + sudo cp $ssl_dir/newcerts/01.pem \ /etc/yunohost/certs/yunohost.org/crt.pem sudo ln -s /etc/yunohost/certs/yunohost.org/crt.pem \ /etc/ssl/certs/yunohost_crt.pem From 29b0088ffc9a1870c8b77d22ae8aa64b6e7fc2e3 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 18:10:35 -0400 Subject: [PATCH 66/86] [fix] Do not increment serial unless YunoHost is postinstalled --- data/hooks/conf_regen/02-ssl | 11 +++++++++++ data/hooks/conf_regen/15-nginx | 2 ++ 2 files changed, 13 insertions(+) diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index 8c54be5e..734df6b0 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -25,6 +25,13 @@ sudo mkdir -p $ssl_dir/{ca,certs,crl,newcerts} safe_copy openssl.cnf $ssl_dir/openssl.cnf +if [ ! -f /etc/yunohost/installed ]; then + sudo rm -f $ssl_dir/index.txt + sudo touch $ssl_dir/index.txt + sudo rm -f $ssl_dir/serial + sudo rm -f /etc/yunohost/certs/yunohost.org/* +fi + if [ ! -f $ssl_dir/serial ]; then echo "01" | sudo tee $ssl_dir/serial fi @@ -42,6 +49,10 @@ if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then sudo openssl ca -config $ssl_dir/openssl.cnf \ -days 730 -in $ssl_dir/certs/yunohost_csr.pem \ -out $ssl_dir/certs/yunohost_crt.pem -batch + + sudo chmod 640 $ssl_dir/certs/yunohost_key.pem + sudo chmod 640 $ssl_dir/newcerts/01.pem + sudo cp $ssl_dir/ca/cacert.pem \ /etc/yunohost/certs/yunohost.org/ca.pem sudo cp $ssl_dir/certs/yunohost_key.pem \ diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index a3754a45..72c03f18 100644 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -72,6 +72,8 @@ if [ -f /etc/yunohost/installed ]; then done else + [ ! -f /etc/nginx/sites-available/default ] \ + || rm -f /etc/nginx/sites-enabled/default need_restart=True fi From 784a5f34d718b11ec81a2fd14df2d950217aa9e1 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 18:23:09 -0400 Subject: [PATCH 67/86] [fix] Force symbolic links to base SSL certs --- data/hooks/conf_regen/02-ssl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index 734df6b0..20af045f 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -59,11 +59,11 @@ if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then /etc/yunohost/certs/yunohost.org/key.pem sudo cp $ssl_dir/newcerts/01.pem \ /etc/yunohost/certs/yunohost.org/crt.pem - sudo ln -s /etc/yunohost/certs/yunohost.org/crt.pem \ + sudo ln -sf /etc/yunohost/certs/yunohost.org/crt.pem \ /etc/ssl/certs/yunohost_crt.pem - sudo ln -s /etc/yunohost/certs/yunohost.org/key.pem \ + sudo ln -sf/etc/yunohost/certs/yunohost.org/key.pem \ /etc/ssl/private/yunohost_key.pem - sudo ln -s /etc/yunohost/certs/yunohost.org/ca.pem \ + sudo ln -sf /etc/yunohost/certs/yunohost.org/ca.pem \ /etc/ssl/certs/ca-yunohost_crt.pem sudo update-ca-certificates fi From f285a5edce793731e19b98479622299a9c2f7b13 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 18:32:33 -0400 Subject: [PATCH 68/86] [fix] Set a MySQL password at moulinette installation --- data/hooks/conf_regen/34-mysql | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/data/hooks/conf_regen/34-mysql b/data/hooks/conf_regen/34-mysql index 62d9d2b2..021e4537 100644 --- a/data/hooks/conf_regen/34-mysql +++ b/data/hooks/conf_regen/34-mysql @@ -13,8 +13,24 @@ function safe_copy () { fi } +function randpass () { + [ "$2" == "0" ] && CHAR="[:alnum:]" || CHAR="[:graph:]" + cat /dev/urandom | tr -cd "$CHAR" | head -c ${1:-32} + echo +} + cd /usr/share/yunohost/templates/mysql if [[ "$(safe_copy my.cnf /etc/mysql/my.cnf)" == "True" ]]; then sudo service mysql restart fi + +if [ ! -f /etc/yunohost/mysql ]; then + [[ $(/bin/ps aux | grep mysqld | grep -vc "grep") == "0" ]] \ + && sudo service mysql start + + mysql_password=$(randpass 10 0) + sudo mysqladmin -u root -pyunohost password $mysql_password + echo $mysql_password | sudo tee /etc/yunohost/mysql + sudo chmod 400 /etc/yunohost/mysql +fi From 0247d52ea2498dd5a9f1b36fd97cb76dcfaf233c Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 18:37:36 -0400 Subject: [PATCH 69/86] [fix] Typo --- data/hooks/conf_regen/02-ssl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index 20af045f..73eba949 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -61,7 +61,7 @@ if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then /etc/yunohost/certs/yunohost.org/crt.pem sudo ln -sf /etc/yunohost/certs/yunohost.org/crt.pem \ /etc/ssl/certs/yunohost_crt.pem - sudo ln -sf/etc/yunohost/certs/yunohost.org/key.pem \ + sudo ln -sf /etc/yunohost/certs/yunohost.org/key.pem \ /etc/ssl/private/yunohost_key.pem sudo ln -sf /etc/yunohost/certs/yunohost.org/ca.pem \ /etc/ssl/certs/ca-yunohost_crt.pem From 7b308a0fc21b15c582b188c2d092029f8235870d Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 18:50:05 -0400 Subject: [PATCH 70/86] [fix] slapd configuration needed for postinstall --- data/hooks/conf_regen/06-slapd | 25 +++++++++++++++---------- debian/postinst | 1 + 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd index b711ae0b..2d3ef7f9 100644 --- a/data/hooks/conf_regen/06-slapd +++ b/data/hooks/conf_regen/06-slapd @@ -4,23 +4,28 @@ set -e force=$1 function safe_copy () { - if [[ "$force" == "True" ]]; then - sudo yunohost service safecopy \ - -s slapd \ - $1 $2 \ - --force + if [ ! -f /etc/yunohost/installed ]; then + sudo cp $1 $2 else - sudo yunohost service safecopy \ - -s slapd \ - $1 $2 + if [[ "$force" == "True" ]]; then + sudo yunohost service safecopy \ + -s slapd \ + $1 $2 \ + --force + else + sudo yunohost service safecopy \ + -s slapd \ + $1 $2 + fi fi } cd /usr/share/yunohost/templates/slapd # Remove legacy configuration file -sudo yunohost service saferemove -s slapd \ - /etc/ldap/slapd-yuno.conf +[ ! -f /etc/yunohost/installed ] \ + || sudo yunohost service saferemove -s slapd \ + /etc/ldap/slapd-yuno.conf safe_copy mailserver.schema /etc/ldap/schema/mailserver.schema safe_copy ldap.conf /etc/ldap/ldap.conf diff --git a/debian/postinst b/debian/postinst index c1159dfd..b40c20c7 100644 --- a/debian/postinst +++ b/debian/postinst @@ -9,6 +9,7 @@ do_configure() { if [ ! -f /etc/yunohost/installed ]; then bash /usr/share/yunohost/hooks/conf_regen/01-yunohost bash /usr/share/yunohost/hooks/conf_regen/02-ssl + bash /usr/share/yunohost/hooks/conf_regen/06-slapd bash /usr/share/yunohost/hooks/conf_regen/15-nginx fi } From bc85d157b5a7ef3b56bb47c74f66100300848150 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 19:04:39 -0400 Subject: [PATCH 71/86] [fix] Copy sudo.schema --- data/hooks/conf_regen/06-slapd | 8 ++-- data/templates/slapd/sudo.schema | 76 ++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 data/templates/slapd/sudo.schema diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd index 2d3ef7f9..63cffac2 100644 --- a/data/hooks/conf_regen/06-slapd +++ b/data/hooks/conf_regen/06-slapd @@ -9,13 +9,10 @@ function safe_copy () { else if [[ "$force" == "True" ]]; then sudo yunohost service safecopy \ - -s slapd \ - $1 $2 \ - --force + -s slapd $1 $2 --force else sudo yunohost service safecopy \ - -s slapd \ - $1 $2 + -s slapd $1 $2 fi fi } @@ -27,6 +24,7 @@ cd /usr/share/yunohost/templates/slapd || sudo yunohost service saferemove -s slapd \ /etc/ldap/slapd-yuno.conf +safe_copy sudo.schema /etc/ldap/schema/sudo.schema safe_copy mailserver.schema /etc/ldap/schema/mailserver.schema safe_copy ldap.conf /etc/ldap/ldap.conf safe_copy slapd.default /etc/default/slapd diff --git a/data/templates/slapd/sudo.schema b/data/templates/slapd/sudo.schema new file mode 100644 index 00000000..d3e95e00 --- /dev/null +++ b/data/templates/slapd/sudo.schema @@ -0,0 +1,76 @@ +# +# OpenLDAP schema file for Sudo +# Save as /etc/openldap/schema/sudo.schema +# + +attributetype ( 1.3.6.1.4.1.15953.9.1.1 + NAME 'sudoUser' + DESC 'User(s) who may run sudo' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.2 + NAME 'sudoHost' + DESC 'Host(s) who may run sudo' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.3 + NAME 'sudoCommand' + DESC 'Command(s) to be executed by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.4 + NAME 'sudoRunAs' + DESC 'User(s) impersonated by sudo (deprecated)' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.5 + NAME 'sudoOption' + DESC 'Options(s) followed by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.6 + NAME 'sudoRunAsUser' + DESC 'User(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.7 + NAME 'sudoRunAsGroup' + DESC 'Group(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.8 + NAME 'sudoNotBefore' + DESC 'Start of time interval for which the entry is valid' + EQUALITY generalizedTimeMatch + ORDERING generalizedTimeOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.9 + NAME 'sudoNotAfter' + DESC 'End of time interval for which the entry is valid' + EQUALITY generalizedTimeMatch + ORDERING generalizedTimeOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) + +attributeTypes ( 1.3.6.1.4.1.15953.9.1.10 + NAME 'sudoOrder' + DESC 'an integer to order the sudoRole entries' + EQUALITY integerMatch + ORDERING integerOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) + +objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL + DESC 'Sudoer Entries' + MUST ( cn ) + MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ + description ) + ) From 8c46e978a3f0c9845e3734cf3d10c0d8e8fbd705 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 19:23:37 -0400 Subject: [PATCH 72/86] [fix] Regenerate configuration files only if YunoHost is postinstalled --- data/templates/slapd/slapd.conf | 1 - lib/yunohost/domain.py | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/data/templates/slapd/slapd.conf b/data/templates/slapd/slapd.conf index e5ac8801..f47e6761 100644 --- a/data/templates/slapd/slapd.conf +++ b/data/templates/slapd/slapd.conf @@ -14,7 +14,6 @@ include /etc/ldap/schema/nis.schema include /etc/ldap/schema/inetorgperson.schema include /etc/ldap/schema/mailserver.schema include /etc/ldap/schema/sudo.schema -include /etc/ldap/schema/samba.schema # Where the pid file is put. The init.d script # will not stop the server if you change this. diff --git a/lib/yunohost/domain.py b/lib/yunohost/domain.py index 434e97e4..9d3d3f74 100644 --- a/lib/yunohost/domain.py +++ b/lib/yunohost/domain.py @@ -159,10 +159,13 @@ def domain_add(auth, domain, dyndns=False): if not auth.add('virtualdomain=%s,ou=domains' % domain, attr_dict): raise MoulinetteError(errno.EIO, m18n.n('domain_creation_failed')) - service_regenconf(service='nginx') - service_regenconf(service='metronome') - service_regenconf(service='dnsmasq') - os.system('yunohost app ssowatconf > /dev/null 2>&1') + try: + with open('/etc/yunohost/installed', 'r') as f: + service_regenconf(service='nginx') + service_regenconf(service='metronome') + service_regenconf(service='dnsmasq') + os.system('yunohost app ssowatconf > /dev/null 2>&1') + except IOError: pass except: # Force domain removal silently try: domain_remove(auth, domain, True) From beec9e4150cfd422eda1ce9a12fc08cc7c9f4b2d Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 19:37:59 -0400 Subject: [PATCH 73/86] [fix] Force configuration at postinstall --- lib/yunohost/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yunohost/tools.py b/lib/yunohost/tools.py index ca31e641..bfa9c1a4 100644 --- a/lib/yunohost/tools.py +++ b/lib/yunohost/tools.py @@ -147,7 +147,7 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False): try: with open('/etc/yunohost/installed', 'r') as f: - service_regenconf() + service_regenconf(force=True) except IOError: pass msignals.display(m18n.n('maindomain_changed'), 'success') From 1c11d8ce94f556cedbf391f014cfad618927d7e6 Mon Sep 17 00:00:00 2001 From: kload Date: Thu, 1 Oct 2015 19:44:18 -0400 Subject: [PATCH 74/86] [fix] Do not mind if backup removal fails --- lib/yunohost/service.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index aa1f9d3e..765598bc 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -464,8 +464,6 @@ def service_saferemove(service, conf_file, force=False): del services[service]['conffiles'][conf_file] except KeyError: pass deleted = True - msignals.display(m18n.n('service_configuration_backup', conf_backup_file), - 'info') else: services[service]['conffiles'][conf_file] = previous_hash os.remove(conf_backup_file) @@ -552,7 +550,9 @@ def service_safecopy(service, new_conf_file, conf_file, force=False): # Remove the backup file if the configuration has not changed if new_hash == previous_hash: - os.remove(conf_backup_file) + try: + os.remove(conf_backup_file) + except OSError: pass elif os.path.exists(conf_backup_file): msignals.display(m18n.n('service_configuration_backup', conf_backup_file), 'info') From 5ff18d3b42dc03490747079462a65ed5b059816e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Fri, 2 Oct 2015 02:10:04 +0200 Subject: [PATCH 75/86] [enh] Review yunohost-api init service and add systemd compat --- debian/control | 6 +- debian/rules | 2 +- debian/yunohost-api.init | 160 ++++++++++++++++++++++++------------ debian/yunohost-api.service | 11 +++ 4 files changed, 121 insertions(+), 58 deletions(-) create mode 100644 debian/yunohost-api.service diff --git a/debian/control b/debian/control index 4c96298d..99bd791b 100644 --- a/debian/control +++ b/debian/control @@ -1,9 +1,9 @@ Source: moulinette-yunohost Section: net Priority: extra -Maintainer: Jérôme Lebleu -Build-Depends: debhelper (>=8.0.0) -Standards-Version: 3.9.4 +Maintainer: YunoHost Contributors +Build-Depends: debhelper (>=9), dh-systemd +Standards-Version: 3.9.6 Homepage: https://yunohost.org/ Package: moulinette-yunohost diff --git a/debian/rules b/debian/rules index 794068d8..5de55b6d 100755 --- a/debian/rules +++ b/debian/rules @@ -5,7 +5,7 @@ #export DH_VERBOSE=1 %: - dh $@ + dh ${@} --with=systemd override_dh_installinit: dh_installinit --name=yunohost-api diff --git a/debian/yunohost-api.init b/debian/yunohost-api.init index 3e75e159..0a27554d 100755 --- a/debian/yunohost-api.init +++ b/debian/yunohost-api.init @@ -1,75 +1,127 @@ -#! /bin/bash +#! /bin/sh + ### BEGIN INIT INFO # Provides: yunohost-api # Required-Start: $local_fs $remote_fs $network $syslog # Required-Stop: $local_fs $remote_fs $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Short-Description: Start/stop YunoHost API -# Description: Start/stop YunoHost API +# Short-Description: Manage YunoHost API Server +# Description: Manage YunoHost API Server ### END INIT INFO -DAEMON=/usr/bin/yunohost-api +set -e + +DESC="YunoHost API Server" +NAME="yunohost-api" +DAEMON=/usr/bin/$NAME DAEMON_OPTS="" +PATH=/sbin:/usr/sbin:/bin:/usr/bin +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME +LOGFILE=/var/log/$NAME.log -test -x $DAEMON || exit 0 +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. . /lib/lsb/init-functions -logger "YunoHost API: Start script executed" +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --background --make-pidfile --quiet --no-close \ + --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS >>$LOGFILE 2>&1 \ + || return 2 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --oknodo --pidfile $PIDFILE + RETVAL="$?" + + sleep 1 + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # Send a SIGHUP to reload the daemon. + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} case "$1" in start) - logger "YunoHost API: Starting" - log_daemon_msg "Starting API: YunoHost" - if [[ -f /etc/nginx/conf.d/openresty.conf ]]; - then - DAEMON_OPTS="--no-websocket" - fi - start-stop-daemon --start --background --pidfile /var/run/yunohost-api.pid --make-pidfile \ - --exec /bin/bash -- -c "$DAEMON $DAEMON_OPTS >> /var/log/yunohost.log 2>&1" - log_end_msg $? - ;; + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; stop) - logger "YunoHost API: Stopping" - log_daemon_msg "Stopping API: YunoHost" - if [ -f /var/run/yunohost-api.pid ]; then - kill `cat /var/run/yunohost-api.pid` > /dev/null 2>&1 - rm -f /var/run/yunohost-api.pid - fi - kill `ps aux | grep 'python /usr/bin/yunohost-api' | grep -v grep | awk '{print $2}'` > /dev/null 2>&1 - kill `ps aux | grep 'yunohost-api' | grep -v grep | grep -v stop | awk '{print $2}'` > /dev/null 2>&1 - log_end_msg 0 - ;; - restart|force-reload) - logger "YunoHost API: Restarting" - log_daemon_msg "Restarting API: YunoHost" - if [ -f /var/run/yunohost-api.pid ]; then - kill `cat /var/run/yunohost-api.pid` > /dev/null 2>&1 - rm -f /var/run/yunohost-api.pid - fi - kill `ps aux | grep 'python /usr/bin/yunohost-api' | grep -v grep | awk '{print $2}'` > /dev/null 2>&1 - kill `ps aux | grep 'yunohost-api' | grep -v grep | grep -v restart | awk '{print $2}'` > /dev/null 2>&1 - kill `ps aux | grep 'yunohost.tac' | grep -v grep | awk '{print $2}'` > /dev/null 2>&1 - if [[ -f /etc/nginx/conf.d/openresty.conf ]]; - then - DAEMON_OPTS="--no-websocket" - fi - start-stop-daemon --start --background --pidfile /var/run/yunohost-api.pid --make-pidfile \ - --exec /bin/bash -- -c "$DAEMON $DAEMON_OPTS >> /var/log/yunohost.log 2>&1" - log_end_msg $? - ;; + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; status) - logger "YunoHost API: Running" - log_daemon_msg "YunoHost API: Running" - cat /var/run/yunohost-api.pid > /dev/null 2>&1 - log_end_msg $? - ;; + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + reload) + log_daemon_msg "Reloading $DESC" "$NAME" + do_reload + log_end_msg $? + ;; + restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; *) - logger "YunoHost API: Invalid usage" - echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|force-reload|status}" >&2 - exit 1 - ;; + echo "Usage: $SCRIPTNAME {start|stop|status|restart|reload}" >&2 + exit 3 + ;; esac -exit 0 +: diff --git a/debian/yunohost-api.service b/debian/yunohost-api.service new file mode 100644 index 00000000..957baff6 --- /dev/null +++ b/debian/yunohost-api.service @@ -0,0 +1,11 @@ +[Unit] +Description=YunoHost API Server +After=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/yunohost-api +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target From a68c157abe42721912e52f6f852342ed9ffaf062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Fri, 2 Oct 2015 02:36:15 +0200 Subject: [PATCH 76/86] [fix] Enhance copyright and control Debian package files --- debian/control | 11 +- debian/copyright | 1011 +++++++++++++++++++++++++++++++--------------- 2 files changed, 683 insertions(+), 339 deletions(-) diff --git a/debian/control b/debian/control index 99bd791b..147a25f1 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,8 @@ Homepage: https://yunohost.org/ Package: moulinette-yunohost Architecture: all -Depends: moulinette (>= 2.2.1), +Depends: ${misc:Depends}, ${shlibs:Depends}, + moulinette (>= 2.2.1), python-psutil, python-requests, glances, @@ -26,5 +27,9 @@ Depends: moulinette (>= 2.2.1), curl, mariadb-server | mysql-server, php5-mysql | php5-mysqlnd Conflicts: iptables-persistent -Description: YunoHost Python scripts - Python functions to manage a YunoHost instance +Description: YunoHost scripts for the moulinette + YunoHost aims to make self-hosting accessible to everyone. + . + This package contains YunoHost scripts and binaries to be used by the + moulinette. It allows to manage the server with a command-line tool and + an API. diff --git a/debian/copyright b/debian/copyright index d159169d..8dd627ca 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,339 +1,678 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Source: https://github.com/YunoHost/moulinette-yunohost - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Files: * +Copyright: 2015 YUNOHOST.ORG +License: AGPL-3 + +License: AGPL-3 + OPA is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License, version 3, as published by + the Free Software Foundation. + . + OPA is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + more details. + . + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + . + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. + . + Preamble + . + The GNU Affero General Public License is a free, copyleft license for + software and other kinds of works, specifically designed to ensure + cooperation with the community in the case of network server software. + . + The licenses for most software and other practical works are designed + to take away your freedom to share and change the works. By contrast, + our General Public Licenses are intended to guarantee your freedom to + share and change all versions of a program--to make sure it remains free + software for all its users. + . + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + them if you wish), that you receive source code or can get it if you + want it, that you can change the software or use pieces of it in new + free programs, and that you know you can do these things. + . + Developers that use our General Public Licenses protect your rights + with two steps: (1) assert copyright on the software, and (2) offer + you this License which gives you legal permission to copy, distribute + and/or modify the software. + . + A secondary benefit of defending all users' freedom is that + improvements made in alternate versions of the program, if they + receive widespread use, become available for other developers to + incorporate. Many developers of free software are heartened and + encouraged by the resulting cooperation. However, in the case of + software used on network servers, this result may fail to come about. + The GNU General Public License permits making a modified version and + letting the public access it on a server without ever releasing its + source code to the public. + . + The GNU Affero General Public License is designed specifically to + ensure that, in such cases, the modified source code becomes available + to the community. It requires the operator of a network server to + provide the source code of the modified version running there to the + users of that server. Therefore, public use of a modified version, on + a publicly accessible server, gives the public access to the source + code of the modified version. + . + An older license, called the Affero General Public License and + published by Affero, was designed to accomplish similar goals. This is + a different license, not a version of the Affero GPL, but Affero has + released a new version of the Affero GPL which permits relicensing under + this license. + . + The precise terms and conditions for copying, distribution and + modification follow. + . + TERMS AND CONDITIONS + . + 0. Definitions. + . + "This License" refers to version 3 of the GNU Affero General Public License. + . + "Copyright" also means copyright-like laws that apply to other kinds of + works, such as semiconductor masks. + . + "The Program" refers to any copyrightable work licensed under this + License. Each licensee is addressed as "you". "Licensees" and + "recipients" may be individuals or organizations. + . + To "modify" a work means to copy from or adapt all or part of the work + in a fashion requiring copyright permission, other than the making of an + exact copy. The resulting work is called a "modified version" of the + earlier work or a work "based on" the earlier work. + . + A "covered work" means either the unmodified Program or a work based + on the Program. + . + To "propagate" a work means to do anything with it that, without + permission, would make you directly or secondarily liable for + infringement under applicable copyright law, except executing it on a + computer or modifying a private copy. Propagation includes copying, + distribution (with or without modification), making available to the + public, and in some countries other activities as well. + . + To "convey" a work means any kind of propagation that enables other + parties to make or receive copies. Mere interaction with a user through + a computer network, with no transfer of a copy, is not conveying. + . + An interactive user interface displays "Appropriate Legal Notices" + to the extent that it includes a convenient and prominently visible + feature that (1) displays an appropriate copyright notice, and (2) + tells the user that there is no warranty for the work (except to the + extent that warranties are provided), that licensees may convey the + work under this License, and how to view a copy of this License. If + the interface presents a list of user commands or options, such as a + menu, a prominent item in the list meets this criterion. + . + 1. Source Code. + . + The "source code" for a work means the preferred form of the work + for making modifications to it. "Object code" means any non-source + form of a work. + . + A "Standard Interface" means an interface that either is an official + standard defined by a recognized standards body, or, in the case of + interfaces specified for a particular programming language, one that + is widely used among developers working in that language. + . + The "System Libraries" of an executable work include anything, other + than the work as a whole, that (a) is included in the normal form of + packaging a Major Component, but which is not part of that Major + Component, and (b) serves only to enable use of the work with that + Major Component, or to implement a Standard Interface for which an + implementation is available to the public in source code form. A + "Major Component", in this context, means a major essential component + (kernel, window system, and so on) of the specific operating system + (if any) on which the executable work runs, or a compiler used to + produce the work, or an object code interpreter used to run it. + . + The "Corresponding Source" for a work in object code form means all + the source code needed to generate, install, and (for an executable + work) run the object code and to modify the work, including scripts to + control those activities. However, it does not include the work's + System Libraries, or general-purpose tools or generally available free + programs which are used unmodified in performing those activities but + which are not part of the work. For example, Corresponding Source + includes interface definition files associated with source files for + the work, and the source code for shared libraries and dynamically + linked subprograms that the work is specifically designed to require, + such as by intimate data communication or control flow between those + subprograms and other parts of the work. + . + The Corresponding Source need not include anything that users + can regenerate automatically from other parts of the Corresponding + Source. + . + The Corresponding Source for a work in source code form is that + same work. + . + 2. Basic Permissions. + . + All rights granted under this License are granted for the term of + copyright on the Program, and are irrevocable provided the stated + conditions are met. This License explicitly affirms your unlimited + permission to run the unmodified Program. The output from running a + covered work is covered by this License only if the output, given its + content, constitutes a covered work. This License acknowledges your + rights of fair use or other equivalent, as provided by copyright law. + . + You may make, run and propagate covered works that you do not + convey, without conditions so long as your license otherwise remains + in force. You may convey covered works to others for the sole purpose + of having them make modifications exclusively for you, or provide you + with facilities for running those works, provided that you comply with + the terms of this License in conveying all material for which you do + not control copyright. Those thus making or running the covered works + for you must do so exclusively on your behalf, under your direction + and control, on terms that prohibit them from making any copies of + your copyrighted material outside their relationship with you. + . + Conveying under any other circumstances is permitted solely under + the conditions stated below. Sublicensing is not allowed; section 10 + makes it unnecessary. + . + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + . + No covered work shall be deemed part of an effective technological + measure under any applicable law fulfilling obligations under article + 11 of the WIPO copyright treaty adopted on 20 December 1996, or + similar laws prohibiting or restricting circumvention of such + measures. + . + When you convey a covered work, you waive any legal power to forbid + circumvention of technological measures to the extent such circumvention + is effected by exercising rights under this License with respect to + the covered work, and you disclaim any intention to limit operation or + modification of the work as a means of enforcing, against the work's + users, your or third parties' legal rights to forbid circumvention of + technological measures. + . + 4. Conveying Verbatim Copies. + . + You may convey verbatim copies of the Program's source code as you + receive it, in any medium, provided that you conspicuously and + appropriately publish on each copy an appropriate copyright notice; + keep intact all notices stating that this License and any + non-permissive terms added in accord with section 7 apply to the code; + keep intact all notices of the absence of any warranty; and give all + recipients a copy of this License along with the Program. + . + You may charge any price or no price for each copy that you convey, + and you may offer support or warranty protection for a fee. + . + 5. Conveying Modified Source Versions. + . + You may convey a work based on the Program, or the modifications to + produce it from the Program, in the form of source code under the + terms of section 4, provided that you also meet all of these conditions: + . + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + . + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + . + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + . + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + . + A compilation of a covered work with other separate and independent + works, which are not by their nature extensions of the covered work, + and which are not combined with it such as to form a larger program, + in or on a volume of a storage or distribution medium, is called an + "aggregate" if the compilation and its resulting copyright are not + used to limit the access or legal rights of the compilation's users + beyond what the individual works permit. Inclusion of a covered work + in an aggregate does not cause this License to apply to the other + parts of the aggregate. + . + 6. Conveying Non-Source Forms. + . + You may convey a covered work in object code form under the terms + of sections 4 and 5, provided that you also convey the + machine-readable Corresponding Source under the terms of this License, + in one of these ways: + . + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + . + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + . + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + . + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + . + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + . + A separable portion of the object code, whose source code is excluded + from the Corresponding Source as a System Library, need not be + included in conveying the object code work. + . + A "User Product" is either (1) a "consumer product", which means any + tangible personal property which is normally used for personal, family, + or household purposes, or (2) anything designed or sold for incorporation + into a dwelling. In determining whether a product is a consumer product, + doubtful cases shall be resolved in favor of coverage. For a particular + product received by a particular user, "normally used" refers to a + typical or common use of that class of product, regardless of the status + of the particular user or of the way in which the particular user + actually uses, or expects or is expected to use, the product. A product + is a consumer product regardless of whether the product has substantial + commercial, industrial or non-consumer uses, unless such uses represent + the only significant mode of use of the product. + . + "Installation Information" for a User Product means any methods, + procedures, authorization keys, or other information required to install + and execute modified versions of a covered work in that User Product from + a modified version of its Corresponding Source. The information must + suffice to ensure that the continued functioning of the modified object + code is in no case prevented or interfered with solely because + modification has been made. + . + If you convey an object code work under this section in, or with, or + specifically for use in, a User Product, and the conveying occurs as + part of a transaction in which the right of possession and use of the + User Product is transferred to the recipient in perpetuity or for a + fixed term (regardless of how the transaction is characterized), the + Corresponding Source conveyed under this section must be accompanied + by the Installation Information. But this requirement does not apply + if neither you nor any third party retains the ability to install + modified object code on the User Product (for example, the work has + been installed in ROM). + . + The requirement to provide Installation Information does not include a + requirement to continue to provide support service, warranty, or updates + for a work that has been modified or installed by the recipient, or for + the User Product in which it has been modified or installed. Access to a + network may be denied when the modification itself materially and + adversely affects the operation of the network or violates the rules and + protocols for communication across the network. + . + Corresponding Source conveyed, and Installation Information provided, + in accord with this section must be in a format that is publicly + documented (and with an implementation available to the public in + source code form), and must require no special password or key for + unpacking, reading or copying. + . + 7. Additional Terms. + . + "Additional permissions" are terms that supplement the terms of this + License by making exceptions from one or more of its conditions. + Additional permissions that are applicable to the entire Program shall + be treated as though they were included in this License, to the extent + that they are valid under applicable law. If additional permissions + apply only to part of the Program, that part may be used separately + under those permissions, but the entire Program remains governed by + this License without regard to the additional permissions. + . + When you convey a copy of a covered work, you may at your option + remove any additional permissions from that copy, or from any part of + it. (Additional permissions may be written to require their own + removal in certain cases when you modify the work.) You may place + additional permissions on material, added by you to a covered work, + for which you have or can give appropriate copyright permission. + . + Notwithstanding any other provision of this License, for material you + add to a covered work, you may (if authorized by the copyright holders of + that material) supplement the terms of this License with terms: + . + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + . + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + . + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + . + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + . + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + . + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + . + All other non-permissive additional terms are considered "further + restrictions" within the meaning of section 10. If the Program as you + received it, or any part of it, contains a notice stating that it is + governed by this License along with a term that is a further + restriction, you may remove that term. If a license document contains + a further restriction but permits relicensing or conveying under this + License, you may add to a covered work material governed by the terms + of that license document, provided that the further restriction does + not survive such relicensing or conveying. + . + If you add terms to a covered work in accord with this section, you + must place, in the relevant source files, a statement of the + additional terms that apply to those files, or a notice indicating + where to find the applicable terms. + . + Additional terms, permissive or non-permissive, may be stated in the + form of a separately written license, or stated as exceptions; + the above requirements apply either way. + . + 8. Termination. + . + You may not propagate or modify a covered work except as expressly + provided under this License. Any attempt otherwise to propagate or + modify it is void, and will automatically terminate your rights under + this License (including any patent licenses granted under the third + paragraph of section 11). + . + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the copyright + holder fails to notify you of the violation by some reasonable means + prior to 60 days after the cessation. + . + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from that + copyright holder, and you cure the violation prior to 30 days after + your receipt of the notice. + . + Termination of your rights under this section does not terminate the + licenses of parties who have received copies or rights from you under + this License. If your rights have been terminated and not permanently + reinstated, you do not qualify to receive new licenses for the same + material under section 10. + . + 9. Acceptance Not Required for Having Copies. + . + You are not required to accept this License in order to receive or + run a copy of the Program. Ancillary propagation of a covered work + occurring solely as a consequence of using peer-to-peer transmission + to receive a copy likewise does not require acceptance. However, + nothing other than this License grants you permission to propagate or + modify any covered work. These actions infringe copyright if you do + not accept this License. Therefore, by modifying or propagating a + covered work, you indicate your acceptance of this License to do so. + . + 10. Automatic Licensing of Downstream Recipients. + . + Each time you convey a covered work, the recipient automatically + receives a license from the original licensors, to run, modify and + propagate that work, subject to this License. You are not responsible + for enforcing compliance by third parties with this License. + . + An "entity transaction" is a transaction transferring control of an + organization, or substantially all assets of one, or subdividing an + organization, or merging organizations. If propagation of a covered + work results from an entity transaction, each party to that + transaction who receives a copy of the work also receives whatever + licenses to the work the party's predecessor in interest had or could + give under the previous paragraph, plus a right to possession of the + Corresponding Source of the work from the predecessor in interest, if + the predecessor has it or can get it with reasonable efforts. + . + You may not impose any further restrictions on the exercise of the + rights granted or affirmed under this License. For example, you may + not impose a license fee, royalty, or other charge for exercise of + rights granted under this License, and you may not initiate litigation + (including a cross-claim or counterclaim in a lawsuit) alleging that + any patent claim is infringed by making, using, selling, offering for + sale, or importing the Program or any portion of it. + . + 11. Patents. + . + A "contributor" is a copyright holder who authorizes use under this + License of the Program or a work on which the Program is based. The + work thus licensed is called the contributor's "contributor version". + . + A contributor's "essential patent claims" are all patent claims + owned or controlled by the contributor, whether already acquired or + hereafter acquired, that would be infringed by some manner, permitted + by this License, of making, using, or selling its contributor version, + but do not include claims that would be infringed only as a + consequence of further modification of the contributor version. For + purposes of this definition, "control" includes the right to grant + patent sublicenses in a manner consistent with the requirements of + this License. + . + Each contributor grants you a non-exclusive, worldwide, royalty-free + patent license under the contributor's essential patent claims, to + make, use, sell, offer for sale, import and otherwise run, modify and + propagate the contents of its contributor version. + . + In the following three paragraphs, a "patent license" is any express + agreement or commitment, however denominated, not to enforce a patent + (such as an express permission to practice a patent or covenant not to + sue for patent infringement). To "grant" such a patent license to a + party means to make such an agreement or commitment not to enforce a + patent against the party. + . + If you convey a covered work, knowingly relying on a patent license, + and the Corresponding Source of the work is not available for anyone + to copy, free of charge and under the terms of this License, through a + publicly available network server or other readily accessible means, + then you must either (1) cause the Corresponding Source to be so + available, or (2) arrange to deprive yourself of the benefit of the + patent license for this particular work, or (3) arrange, in a manner + consistent with the requirements of this License, to extend the patent + license to downstream recipients. "Knowingly relying" means you have + actual knowledge that, but for the patent license, your conveying the + covered work in a country, or your recipient's use of the covered work + in a country, would infringe one or more identifiable patents in that + country that you have reason to believe are valid. + . + If, pursuant to or in connection with a single transaction or + arrangement, you convey, or propagate by procuring conveyance of, a + covered work, and grant a patent license to some of the parties + receiving the covered work authorizing them to use, propagate, modify + or convey a specific copy of the covered work, then the patent license + you grant is automatically extended to all recipients of the covered + work and works based on it. + . + A patent license is "discriminatory" if it does not include within + the scope of its coverage, prohibits the exercise of, or is + conditioned on the non-exercise of one or more of the rights that are + specifically granted under this License. You may not convey a covered + work if you are a party to an arrangement with a third party that is + in the business of distributing software, under which you make payment + to the third party based on the extent of your activity of conveying + the work, and under which the third party grants, to any of the + parties who would receive the covered work from you, a discriminatory + patent license (a) in connection with copies of the covered work + conveyed by you (or copies made from those copies), or (b) primarily + for and in connection with specific products or compilations that + contain the covered work, unless you entered into that arrangement, + or that patent license was granted, prior to 28 March 2007. + . + Nothing in this License shall be construed as excluding or limiting + any implied license or other defenses to infringement that may + otherwise be available to you under applicable patent law. + . + 12. No Surrender of Others' Freedom. + . + If conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot convey a + covered work so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you may + not convey it at all. For example, if you agree to terms that obligate you + to collect a royalty for further conveying from those to whom you convey + the Program, the only way you could satisfy both those terms and this + License would be to refrain entirely from conveying the Program. + . + 13. Remote Network Interaction; Use with the GNU General Public License. + . + Notwithstanding any other provision of this License, if you modify the + Program, your modified version must prominently offer all users + interacting with it remotely through a computer network (if your version + supports such interaction) an opportunity to receive the Corresponding + Source of your version by providing access to the Corresponding Source + from a network server at no charge, through some standard or customary + means of facilitating copying of software. This Corresponding Source + shall include the Corresponding Source for any work covered by version 3 + of the GNU General Public License that is incorporated pursuant to the + following paragraph. + . + Notwithstanding any other provision of this License, you have + permission to link or combine any covered work with a work licensed + under version 3 of the GNU General Public License into a single + combined work, and to convey the resulting work. The terms of this + License will continue to apply to the part which is the covered work, + but the work with which it is combined will remain governed by version + 3 of the GNU General Public License. + . + 14. Revised Versions of this License. + . + The Free Software Foundation may publish revised and/or new versions of + the GNU Affero General Public License from time to time. Such new versions + will be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + . + Each version is given a distinguishing version number. If the + Program specifies that a certain numbered version of the GNU Affero General + Public License "or any later version" applies to it, you have the + option of following the terms and conditions either of that numbered + version or of any later version published by the Free Software + Foundation. If the Program does not specify a version number of the + GNU Affero General Public License, you may choose any version ever published + by the Free Software Foundation. + . + If the Program specifies that a proxy can decide which future + versions of the GNU Affero General Public License can be used, that proxy's + public statement of acceptance of a version permanently authorizes you + to choose that version for the Program. + . + Later license versions may give you additional or different + permissions. However, no additional obligations are imposed on any + author or copyright holder as a result of your choosing to follow a + later version. + . + 15. Disclaimer of Warranty. + . + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT + HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY + OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM + IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF + ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + . + 16. Limitation of Liability. + . + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS + THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY + GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE + USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), + EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES. + . + 17. Interpretation of Sections 15 and 16. + . + If the disclaimer of warranty and limitation of liability provided + above cannot be given local legal effect according to their terms, + reviewing courts shall apply local law that most closely approximates + an absolute waiver of all civil liability in connection with the + Program, unless a warranty or assumption of liability accompanies a + copy of the Program in return for a fee. + . + END OF TERMS AND CONDITIONS + . + How to Apply These Terms to Your New Programs + . + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + . + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + state the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + . + + Copyright (C) + . + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + . + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + . + Also add information on how to contact you by electronic and paper mail. + . + If your software can interact with users remotely through a computer + network, you should also make sure that it provides a way for users to + get its source. For example, if your program is a web application, its + interface could display a "Source" link that leads users to an archive + of the code. There are many ways you could offer source, and different + solutions will be better for different programs; see section 13 for the + specific requirements. + . + You should also get your employer (if you work as a programmer) or school, + if any, to sign a "copyright disclaimer" for the program, if necessary. + For more information on this, and how to apply and follow the GNU AGPL, see + . From 23e2e9c3602a41e0b7e03fc45dfe4fe9abaf7f5d Mon Sep 17 00:00:00 2001 From: kload Date: Fri, 2 Oct 2015 05:14:30 -0400 Subject: [PATCH 77/86] [enh] Regen the configuration at package upgrade --- debian/postinst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/postinst b/debian/postinst index b40c20c7..2a13c8e8 100644 --- a/debian/postinst +++ b/debian/postinst @@ -11,6 +11,8 @@ do_configure() { bash /usr/share/yunohost/hooks/conf_regen/02-ssl bash /usr/share/yunohost/hooks/conf_regen/06-slapd bash /usr/share/yunohost/hooks/conf_regen/15-nginx + else + yunohost service regenconf fi } From 4e0cbf7215623f8b3a44e111d9363da524c4e1b0 Mon Sep 17 00:00:00 2001 From: kload Date: Fri, 2 Oct 2015 05:33:09 -0400 Subject: [PATCH 78/86] [fix] Indentation fail --- lib/yunohost/domain.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/yunohost/domain.py b/lib/yunohost/domain.py index 9d3d3f74..ee53bb39 100644 --- a/lib/yunohost/domain.py +++ b/lib/yunohost/domain.py @@ -159,13 +159,13 @@ def domain_add(auth, domain, dyndns=False): if not auth.add('virtualdomain=%s,ou=domains' % domain, attr_dict): raise MoulinetteError(errno.EIO, m18n.n('domain_creation_failed')) - try: - with open('/etc/yunohost/installed', 'r') as f: - service_regenconf(service='nginx') - service_regenconf(service='metronome') - service_regenconf(service='dnsmasq') - os.system('yunohost app ssowatconf > /dev/null 2>&1') - except IOError: pass + try: + with open('/etc/yunohost/installed', 'r') as f: + service_regenconf(service='nginx') + service_regenconf(service='metronome') + service_regenconf(service='dnsmasq') + os.system('yunohost app ssowatconf > /dev/null 2>&1') + except IOError: pass except: # Force domain removal silently try: domain_remove(auth, domain, True) From ca0b64bd5b005fe5573f339bd6dbf65bc7390fd5 Mon Sep 17 00:00:00 2001 From: kload Date: Fri, 2 Oct 2015 05:36:33 -0400 Subject: [PATCH 79/86] [fix] Force configuration only at postinstall --- lib/yunohost/tools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/yunohost/tools.py b/lib/yunohost/tools.py index bfa9c1a4..867fc775 100644 --- a/lib/yunohost/tools.py +++ b/lib/yunohost/tools.py @@ -147,7 +147,7 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False): try: with open('/etc/yunohost/installed', 'r') as f: - service_regenconf(force=True) + service_regenconf() except IOError: pass msignals.display(m18n.n('maindomain_changed'), 'success') @@ -276,7 +276,7 @@ def tools_postinstall(domain, password, ignore_dyndns=False): os.system('touch /etc/yunohost/installed') - service_regenconf() + service_regenconf(force=True) msignals.display(m18n.n('yunohost_configured'), 'success') From 6b293e90751886a6416db3b4f5c1bb981b62bc23 Mon Sep 17 00:00:00 2001 From: kload Date: Fri, 2 Oct 2015 07:10:45 -0400 Subject: [PATCH 80/86] [fix] Do not print backup info --- lib/yunohost/service.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/yunohost/service.py b/lib/yunohost/service.py index 765598bc..2a69b4d2 100644 --- a/lib/yunohost/service.py +++ b/lib/yunohost/service.py @@ -553,9 +553,6 @@ def service_safecopy(service, new_conf_file, conf_file, force=False): try: os.remove(conf_backup_file) except OSError: pass - elif os.path.exists(conf_backup_file): - msignals.display(m18n.n('service_configuration_backup', conf_backup_file), - 'info') services[service]['conffiles'][conf_file] = new_hash _save_services(services) From 33b749a9f8ab0033e1e620e11f15037fc2a94edc Mon Sep 17 00:00:00 2001 From: kload Date: Fri, 2 Oct 2015 15:56:46 +0200 Subject: [PATCH 81/86] [fix] Handle SSL generation better --- data/hooks/conf_regen/02-ssl | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index 73eba949..db47b268 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -25,21 +25,21 @@ sudo mkdir -p $ssl_dir/{ca,certs,crl,newcerts} safe_copy openssl.cnf $ssl_dir/openssl.cnf -if [ ! -f /etc/yunohost/installed ]; then - sudo rm -f $ssl_dir/index.txt - sudo touch $ssl_dir/index.txt - sudo rm -f $ssl_dir/serial - sudo rm -f /etc/yunohost/certs/yunohost.org/* -fi +[ -f $ssl_dir/serial ] \ + || (echo "01" | sudo tee $ssl_dir/serial) -if [ ! -f $ssl_dir/serial ]; then - echo "01" | sudo tee $ssl_dir/serial -fi +[ -f $ssl_dir/index.txt ] \ + || sudo touch $ssl_dir/index.txt if [ ! -f /etc/yunohost/certs/yunohost.org/ca.pem ]; then sudo openssl req -x509 -new -config $ssl_dir/openssl.cnf \ -days 3650 -out $ssl_dir/ca/cacert.pem \ -keyout $ssl_dir/ca/cakey.pem -nodes -batch + sudo cp $ssl_dir/ca/cacert.pem \ + /etc/yunohost/certs/yunohost.org/ca.pem + sudo ln -sf /etc/yunohost/certs/yunohost.org/ca.pem \ + /etc/ssl/certs/ca-yunohost_crt.pem + sudo update-ca-certificates fi if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then @@ -50,20 +50,16 @@ if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then -days 730 -in $ssl_dir/certs/yunohost_csr.pem \ -out $ssl_dir/certs/yunohost_crt.pem -batch + last_cert=$(ls *.pem | sort -V | tail -n 1) sudo chmod 640 $ssl_dir/certs/yunohost_key.pem - sudo chmod 640 $ssl_dir/newcerts/01.pem + sudo chmod 640 $ssl_dir/newcerts/$last_cert - sudo cp $ssl_dir/ca/cacert.pem \ - /etc/yunohost/certs/yunohost.org/ca.pem sudo cp $ssl_dir/certs/yunohost_key.pem \ /etc/yunohost/certs/yunohost.org/key.pem - sudo cp $ssl_dir/newcerts/01.pem \ + sudo cp $ssl_dir/newcerts/$last_cert \ /etc/yunohost/certs/yunohost.org/crt.pem sudo ln -sf /etc/yunohost/certs/yunohost.org/crt.pem \ /etc/ssl/certs/yunohost_crt.pem sudo ln -sf /etc/yunohost/certs/yunohost.org/key.pem \ /etc/ssl/private/yunohost_key.pem - sudo ln -sf /etc/yunohost/certs/yunohost.org/ca.pem \ - /etc/ssl/certs/ca-yunohost_crt.pem - sudo update-ca-certificates fi From 4e3968fd96b59c61a53daf8820a3399872d9df8f Mon Sep 17 00:00:00 2001 From: kload Date: Fri, 2 Oct 2015 10:11:53 -0400 Subject: [PATCH 82/86] [fix] Modify app list URL to have a proper SSL certificate --- lib/yunohost/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/yunohost/app.py b/lib/yunohost/app.py index 01c93960..bb267cfb 100644 --- a/lib/yunohost/app.py +++ b/lib/yunohost/app.py @@ -66,7 +66,7 @@ def app_fetchlist(url=None, name=None): Keyword argument: name -- Name of the list (default yunohost) - url -- URL of remote JSON list (default https://app.yunohost.org/list.json) + url -- URL of remote JSON list (default https://yunohost.org/list.json) """ # Create app path if not exists @@ -74,7 +74,7 @@ def app_fetchlist(url=None, name=None): except OSError: os.makedirs(repo_path) if url is None: - url = 'https://app.yunohost.org/list.json' + url = 'https://yunohost.org/list.json' name = 'yunohost' else: if name is None: From f0f060345b29542986cb7503b9210332e9eb3f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Fri, 2 Oct 2015 19:04:15 +0200 Subject: [PATCH 83/86] [fix] Ensure that the service yunohost-api is always running --- debian/yunohost-api.service | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/yunohost-api.service b/debian/yunohost-api.service index 957baff6..c7a913b6 100644 --- a/debian/yunohost-api.service +++ b/debian/yunohost-api.service @@ -6,6 +6,8 @@ After=network.target Type=simple ExecStart=/usr/bin/yunohost-api ExecReload=/bin/kill -HUP $MAINPID +Restart=always +RestartSec=1 [Install] WantedBy=multi-user.target From 898620e59dc0fe0b265cbae4299dda871483ceda Mon Sep 17 00:00:00 2001 From: kload Date: Fri, 2 Oct 2015 20:42:27 +0200 Subject: [PATCH 84/86] [fix] SSL paths --- data/hooks/conf_regen/02-ssl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index db47b268..45809d32 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -50,13 +50,13 @@ if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then -days 730 -in $ssl_dir/certs/yunohost_csr.pem \ -out $ssl_dir/certs/yunohost_crt.pem -batch - last_cert=$(ls *.pem | sort -V | tail -n 1) + last_cert=$(ls $ssl_dir/newcerts/*.pem | sort -V | tail -n 1) sudo chmod 640 $ssl_dir/certs/yunohost_key.pem - sudo chmod 640 $ssl_dir/newcerts/$last_cert + sudo chmod 640 $last_cert sudo cp $ssl_dir/certs/yunohost_key.pem \ /etc/yunohost/certs/yunohost.org/key.pem - sudo cp $ssl_dir/newcerts/$last_cert \ + sudo cp $last_cert \ /etc/yunohost/certs/yunohost.org/crt.pem sudo ln -sf /etc/yunohost/certs/yunohost.org/crt.pem \ /etc/ssl/certs/yunohost_crt.pem From 0e76b823608993c5d6b06ad473dc2f2f6648e31c Mon Sep 17 00:00:00 2001 From: kload Date: Fri, 2 Oct 2015 23:34:05 +0200 Subject: [PATCH 85/86] [fix] begin serial at 00 for SSL cert generation --- data/hooks/conf_regen/02-ssl | 2 +- data/hooks/conf_regen/15-nginx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index 45809d32..64614ffa 100644 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -26,7 +26,7 @@ sudo mkdir -p $ssl_dir/{ca,certs,crl,newcerts} safe_copy openssl.cnf $ssl_dir/openssl.cnf [ -f $ssl_dir/serial ] \ - || (echo "01" | sudo tee $ssl_dir/serial) + || (echo "00" | sudo tee $ssl_dir/serial) [ -f $ssl_dir/index.txt ] \ || sudo touch $ssl_dir/index.txt diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 72c03f18..e5a8716b 100644 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -36,12 +36,6 @@ done if [ -f /etc/yunohost/installed ]; then - # Copy 'yunohost.local' to the main domain conf directory - main_domain=$(cat /etc/yunohost/current_host) - safe_copy yunohost_local.conf \ - /etc/nginx/conf.d/$main_domain.d/yunohost_local.conf - - need_restart=False domain_list=$(sudo yunohost domain list --plain) @@ -61,6 +55,12 @@ if [ -f /etc/yunohost/installed ]; then done + # Copy 'yunohost.local' to the main domain conf directory + main_domain=$(cat /etc/yunohost/current_host) + safe_copy yunohost_local.conf \ + /etc/nginx/conf.d/$main_domain.d/yunohost_local.conf + + # Remove old domains files for file in /etc/nginx/conf.d/*.*.conf; do domain=$(echo $file \ From 8668ffa2ff62ed3bc1ec9a40e1d0160aef863f94 Mon Sep 17 00:00:00 2001 From: kload Date: Sat, 3 Oct 2015 03:18:22 +0200 Subject: [PATCH 86/86] [yolo] Merge all packages into one --- debian/control | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/debian/control b/debian/control index 147a25f1..3926f72f 100644 --- a/debian/control +++ b/debian/control @@ -1,12 +1,12 @@ -Source: moulinette-yunohost -Section: net +Source: yunohost +Section: utils Priority: extra Maintainer: YunoHost Contributors Build-Depends: debhelper (>=9), dh-systemd Standards-Version: 3.9.6 Homepage: https://yunohost.org/ -Package: moulinette-yunohost +Package: yunohost Architecture: all Depends: ${misc:Depends}, ${shlibs:Depends}, moulinette (>= 2.2.1), @@ -14,7 +14,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, python-requests, glances, python-pip, - pyminiupnpc, + python-miniupnpc | pyminiupnpc, dnsutils, bind9utils, python-apt, @@ -26,8 +26,21 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, git-core, curl, mariadb-server | mysql-server, php5-mysql | php5-mysqlnd + slapd, ldap-utils, sudo-ldap, libnss-ldapd, + postfix-ldap, postfix-policyd-spf-perl, postfix-pcre, postgrey, + dovecot-ldap, dovecot-lmtpd, dovecot-managesieved, + amavisd-new, razor, pyzor, dovecot-antispam, spamassassin, fail2ban, + nginx-extras (>=1.6.2), php5-fpm, php5-ldap, php5-intl, + dnsmasq, openssl, avahi-daemon, + ssowat, metronome +Recommends: yunohost-admin, + bash-completion, rsyslog, ntp, openssh-server, + php5-gd, php5-curl, php-gettext, php5-mcrypt, + udisks-glue, unattended-upgrades, + libdbd-ldap-perl, libnet-dns-perl +Suggests: htop, vim, rsync, acpi-support-base Conflicts: iptables-persistent -Description: YunoHost scripts for the moulinette +Description: YunoHost installation package YunoHost aims to make self-hosting accessible to everyone. . This package contains YunoHost scripts and binaries to be used by the