Merge branch 'stretch-unstable' of https://github.com/YunoHost/yunohost into stretch-unstable

This commit is contained in:
Weblate 2018-11-01 14:29:08 +00:00
commit 29af304627
21 changed files with 420 additions and 184 deletions

View file

@ -56,7 +56,7 @@ else
echo "$LOGO_AND_FINGERPRINTS" echo "$LOGO_AND_FINGERPRINTS"
echo -e "\e[m Post-installation \e[0m" echo -e "\e[m Post-installation \e[0m"
echo "Congratulations! YunoHost has been successfully installed.\nTwo more steps are required to activate the services of your server." echo "Congratulations! YunoHost has been successfully installed.\nTwo more steps are required to activate the services of your server."
read -p "Proceed to post-installation? (y/n) " -n 1 read -p "Proceed to post-installation? (y/n)\nAlternatively, you can proceed the post-installation on https://${ip}" -n 1
RESULT=1 RESULT=1
while [ $RESULT -gt 0 ]; do while [ $RESULT -gt 0 ]; do
if [[ $REPLY =~ ^[Nn]$ ]]; then if [[ $REPLY =~ ^[Nn]$ ]]; then

View file

@ -105,7 +105,7 @@ user:
ask: ask_lastname ask: ask_lastname
required: True required: True
pattern: &pattern_lastname pattern: &pattern_lastname
- !!str ^([^\W\d_]{2,30}[ ,.']{0,3})+$ - !!str ^([^\W\d_]{2,30}[ ,.'-]{0,3})+$
- "pattern_lastname" - "pattern_lastname"
-m: -m:
full: --mail full: --mail

View file

@ -299,6 +299,23 @@ ynh_backup_if_checksum_is_different () {
fi fi
} }
# Delete a file checksum from the app settings
#
# $app should be defined when calling this helper
#
# usage: ynh_remove_file_checksum file
# | arg: -f, --file= - The file for which the checksum will be deleted
ynh_delete_file_checksum () {
# Declare an array to define the options of this helper.
declare -Ar args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
ynh_app_setting_delete $app $checksum_setting_name
}
# Remove a file or a directory securely # Remove a file or a directory securely
# #
# usage: ynh_secure_remove path_to_remove # usage: ynh_secure_remove path_to_remove

194
data/helpers.d/getopts Normal file
View file

@ -0,0 +1,194 @@
#!/bin/bash
# Internal helper design to allow helpers to use getopts to manage their arguments
#
# [internal]
#
# example: function my_helper()
# {
# declare -Ar args_array=( [a]=arg1= [b]=arg2= [c]=arg3 )
# local arg1
# local arg2
# local arg3
# ynh_handle_getopts_args "$@"
#
# [...]
# }
# my_helper --arg1 "val1" -b val2 -c
#
# usage: ynh_handle_getopts_args "$@"
# | arg: $@ - Simply "$@" to tranfert all the positionnal arguments to the function
#
# This helper need an array, named "args_array" with all the arguments used by the helper
# that want to use ynh_handle_getopts_args
# Be carreful, this array has to be an associative array, as the following example:
# declare -Ar args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
# Let's explain this array:
# a, b and c are short options, -a, -b and -c
# arg1, arg2 and arg3 are the long options associated to the previous short ones. --arg1, --arg2 and --arg3
# For each option, a short and long version has to be defined.
# Let's see something more significant
# declare -Ar args_array=( [u]=user [f]=finalpath= [d]=database )
#
# NB: Because we're using 'declare' without -g, the array will be declared as a local variable.
#
# Please keep in mind that the long option will be used as a variable to store the values for this option.
# For the previous example, that means that $finalpath will be fill with the value given as argument for this option.
#
# Also, in the previous example, finalpath has a '=' at the end. That means this option need a value.
# So, the helper has to be call with --finalpath /final/path, --finalpath=/final/path or -f /final/path, the variable $finalpath will get the value /final/path
# If there's many values for an option, -f /final /path, the value will be separated by a ';' $finalpath=/final;/path
# For an option without value, like --user in the example, the helper can be called only with --user or -u. $user will then get the value 1.
#
# To keep a retrocompatibility, a package can still call a helper, using getopts, with positional arguments.
# The "legacy mode" will manage the positional arguments and fill the variable in the same order than they are given in $args_array.
# e.g. for `my_helper "val1" val2`, arg1 will be filled with val1, and arg2 with val2.
ynh_handle_getopts_args () {
# Manage arguments only if there's some provided
set +x
if [ $# -ne 0 ]
then
# Store arguments in an array to keep each argument separated
local arguments=("$@")
# For each option in the array, reduce to short options for getopts (e.g. for [u]=user, --user will be -u)
# And built parameters string for getopts
# ${!args_array[@]} is the list of all keys in the array (A key is 'u' in [u]=user, user is a value)
local getopts_parameters=""
local key=""
for key in "${!args_array[@]}"
do
# Concatenate each keys of the array to build the string of arguments for getopts
# Will looks like 'abcd' for -a -b -c -d
# If the value of a key finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob)
# Check the last character of the value associate to the key
if [ "${args_array[$key]: -1}" = "=" ]
then
# For an option with additionnal values, add a ':' after the letter for getopts.
getopts_parameters="${getopts_parameters}${key}:"
else
getopts_parameters="${getopts_parameters}${key}"
fi
# Check each argument given to the function
local arg=""
# ${#arguments[@]} is the size of the array
for arg in `seq 0 $(( ${#arguments[@]} - 1 ))`
do
# And replace long option (value of the key) by the short option, the key itself
# (e.g. for [u]=user, --user will be -u)
# Replace long option with =
arguments[arg]="${arguments[arg]//--${args_array[$key]}/-${key} }"
# And long option without =
arguments[arg]="${arguments[arg]//--${args_array[$key]%=}/-${key}}"
done
done
# Read and parse all the arguments
# Use a function here, to use standart arguments $@ and be able to use shift.
parse_arg () {
# Read all arguments, until no arguments are left
while [ $# -ne 0 ]
do
# Initialize the index of getopts
OPTIND=1
# Parse with getopts only if the argument begin by -, that means the argument is an option
# getopts will fill $parameter with the letter of the option it has read.
local parameter=""
getopts ":$getopts_parameters" parameter || true
if [ "$parameter" = "?" ]
then
ynh_die "Invalid argument: -${OPTARG:-}"
elif [ "$parameter" = ":" ]
then
ynh_die "-$OPTARG parameter requires an argument."
else
local shift_value=1
# Use the long option, corresponding to the short option read by getopts, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$parameter]%=}"
# If this option doesn't take values
# if there's a '=' at the end of the long option name, this option takes values
if [ "${args_array[$parameter]: -1}" != "=" ]
then
# 'eval ${option_var}' will use the content of 'option_var'
eval ${option_var}=1
else
# Read all other arguments to find multiple value for this option.
# Load args in a array
local all_args=("$@")
# If the first argument is longer than 2 characters,
# There's a value attached to the option, in the same array cell
if [ ${#all_args[0]} -gt 2 ]; then
# Remove the option and the space, so keep only the value itself.
all_args[0]="${all_args[0]#-${parameter} }"
# Reduce the value of shift, because the option has been removed manually
shift_value=$(( shift_value - 1 ))
fi
# Then read the array value per value
for i in `seq 0 $(( ${#all_args[@]} - 1 ))`
do
# If this argument is an option, end here.
if [ "${all_args[$i]:0:1}" == "-" ] || [ -z "${all_args[$i]}" ]
then
# Ignore the first value of the array, which is the option itself
if [ "$i" -ne 0 ]; then
break
fi
else
# Declare the content of option_var as a variable.
eval ${option_var}=""
# Else, add this value to this option
# Each value will be separated by ';'
if [ -n "${!option_var}" ]
then
# If there's already another value for this option, add a ; before adding the new value
eval ${option_var}+="\;"
fi
eval ${option_var}+=\"${all_args[$i]}\"
shift_value=$(( shift_value + 1 ))
fi
done
fi
fi
# Shift the parameter and its argument(s)
shift $shift_value
done
}
# LEGACY MODE
# Check if there's getopts arguments
if [ "${arguments[0]:0:1}" != "-" ]
then
# If not, enter in legacy mode and manage the arguments as positionnal ones.
echo "! Helper used in legacy mode !"
for i in `seq 0 $(( ${#arguments[@]} -1 ))`
do
# Use getopts_parameters as a list of key of the array args_array
# Remove all ':' in getopts_parameters
getopts_parameters=${getopts_parameters//:}
# Get the key from getopts_parameters, by using the key according to the position of the argument.
key=${getopts_parameters:$i:1}
# Use the long option, corresponding to the key, as a variable
# (e.g. for [u]=user, 'user' will be used as a variable)
# Also, remove '=' at the end of the long option
# The variable name will be stored in 'option_var'
local option_var="${args_array[$key]%=}"
# Store each value given as argument in the corresponding variable
# The values will be stored in the same order than $args_array
eval ${option_var}+=\"${arguments[$i]}\"
done
else
# END LEGACY MODE
# Call parse_arg and pass the modified list of args as an array of arguments.
parse_arg "${arguments[@]}"
fi
fi
set -x
}

View file

@ -173,7 +173,7 @@ ynh_setup_source () {
then # Use the local source file if it is present then # Use the local source file if it is present
cp $local_src $src_filename cp $local_src $src_filename
else # If not, download the source else # If not, download the source
wget -nv -O $src_filename $src_url local out=`wget -nv -O $src_filename $src_url 2>&1` || ynh_print_err $out
fi fi
# Check the control sum # Check the control sum
@ -253,6 +253,9 @@ ynh_local_curl () {
# Add --data arg and remove the last character, which is an unecessary '&' # Add --data arg and remove the last character, which is an unecessary '&'
POST_data="--data ${POST_data::-1}" POST_data="--data ${POST_data::-1}"
fi fi
# Wait untils nginx has fully reloaded (avoid curl fail with http2)
sleep 2
# Curl the URL # Curl the URL
curl --silent --show-error -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url" curl --silent --show-error -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url"

View file

@ -2,6 +2,8 @@
set -e set -e
. /usr/share/yunohost/helpers.d/utils
do_init_regen() { do_init_regen() {
if [[ $EUID -ne 0 ]]; then if [[ $EUID -ne 0 ]]; then
echo "You must be root to run this script" 1>&2 echo "You must be root to run this script" 1>&2
@ -42,18 +44,18 @@ do_pre_regen() {
mkdir -p "$mail_autoconfig_dir" mkdir -p "$mail_autoconfig_dir"
# NGINX server configuration # NGINX server configuration
cat server.tpl.conf \ export domain
| sed "s/{{ domain }}/${domain}/g" \ export domain_cert_ca=$(yunohost domain cert-status $domain --json \
> "${nginx_conf_dir}/${domain}.conf" | jq ".certificates.\"$domain\".CA_type" \
| tr -d '"')
cat autoconfig.tpl.xml \
| sed "s/{{ domain }}/${domain}/g" \
> "${mail_autoconfig_dir}/config-v1.1.xml"
ynh_render_template "server.tpl.conf" "${nginx_conf_dir}/${domain}.conf"
ynh_render_template "autoconfig.tpl.xml" "${mail_autoconfig_dir}/config-v1.1.xml"
[[ $main_domain != $domain ]] \ [[ $main_domain != $domain ]] \
&& touch "${domain_conf_dir}/yunohost_local.conf" \ && touch "${domain_conf_dir}/yunohost_local.conf" \
|| cp yunohost_local.conf "${domain_conf_dir}/yunohost_local.conf" || cp yunohost_local.conf "${domain_conf_dir}/yunohost_local.conf"
done done
# remove old domain conf files # remove old domain conf files

View file

@ -9,16 +9,64 @@
-- A table is a list of values, except each value has a name. An -- A table is a list of values, except each value has a name. An
-- example would be: -- example would be:
-- --
-- ssl = { key = "keyfile.key", certificate = "certificate.crt" } -- ssl = { key = "keyfile.key", certificate = "certificate.cert" }
-- --
-- Tip: You can check that the syntax of this file is correct when you have finished -- Tip: You can check that the syntax of this file is correct when you have finished
-- by running: luac -p metronome.cfg.lua -- by running: luac -p metronome.cfg.lua
-- If there are any errors, it will let you know what and where they are, otherwise it -- If there are any errors, it will let you know what and where they are, otherwise it
-- will keep quiet. -- will keep quiet.
---------- Server-wide settings ---------- -- Global settings go in this section
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts -- 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. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"disco"; -- Service discovery
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
"pep"; -- Allows setting of mood, tune, etc.
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
"bidi"; -- Enables Bidirectional Server-to-Server Streams.
-- 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
"register"; -- Allow users to register on this server using a client and change passwords
"stream_management"; -- Allows clients and servers to use Stream Management
"stanza_optimizations"; -- Allows clients to use Client State Indication and SIFT
"message_carbons"; -- Allows clients to enable carbon copies of messages
"mam"; -- Enable server-side message archives using Message Archive Management
"push"; -- Enable Push Notifications via PubSub using XEP-0357
"lastactivity"; -- Enables clients to know the last presence status of an user
"adhoc_cm"; -- Allow to set client certificates to login through SASL External via adhoc
"admin_adhoc"; -- administration adhoc commands
"bookmarks"; -- XEP-0048 Bookmarks synchronization between PEP and Private Storage
"sec_labels"; -- Allows to use a simplified version XEP-0258 Security Labels and related ACDFs.
"privacy"; -- Add privacy lists and simple blocking command support
-- Other specific functionality
--"admin_telnet"; -- administration console, telnet to port 5582
--"admin_web"; -- administration web interface
"bosh"; -- Enable support for BOSH clients, aka "XMPP over Bidirectional Streams over Synchronous HTTP"
--"compression"; -- Allow clients to enable Stream Compression
--"spim_block"; -- Require authorization via OOB form for messages from non-contacts and block unsollicited messages
--"gate_guard"; -- Enable config-based blacklisting and hit-based auto-banning features
--"incidents_handling"; -- Enable Incidents Handling support (can be administered via adhoc commands)
--"server_presence"; -- Enables Server Buddies extension support
--"service_directory"; -- Enables Service Directories extension support
--"public_service"; -- Enables Server vCard support for public services in directories and advertises in features
--"register_api"; -- Provides secure API for both Out-Of-Band and In-Band registration for E-Mail verification
"websocket"; -- Enable support for WebSocket clients, aka "XMPP over WebSockets"
};
-- Server PID -- Server PID
pidfile = "/var/run/metronome/metronome.pid" pidfile = "/var/run/metronome/metronome.pid"
@ -33,156 +81,76 @@ http_interfaces = { "127.0.0.1", "::1" }
-- Enable IPv6 -- Enable IPv6
use_ipv6 = true 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 -- Discovery items
disco_items = { disco_items = {
{ "muc.{{ main_domain }}" }, { "muc.{{ main_domain }}" },
{ "pubsub.{{ main_domain }}" }, { "pubsub.{{ main_domain }}" },
{ "vjud.{{ main_domain }}" } { "upload.{{ main_domain }}" },
{ "vjud.{{ main_domain }}" }
}; };
-- BOSH configuration (mod_bosh) -- BOSH configuration (mod_bosh)
bosh_max_inactivity = 30
consider_bosh_secure = true consider_bosh_secure = true
cross_domain_bosh = true cross_domain_bosh = true
-- WebSocket configuration (mod_websocket)
consider_websocket_secure = true
cross_domain_websocket = true
-- Disable account creation by default, for security -- Disable account creation by default, for security
allow_registration = false 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 -- Use LDAP storage backend for all stores
storage = "ldap" storage = "ldap"
-- Logging configuration -- Logging configuration
log = { log = {
info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/metronome/metronome.err"; error = "/var/log/metronome/metronome.err";
-- "*syslog"; -- Uncomment this for logging to syslog -- "*syslog"; -- Uncomment this for logging to syslog
-- "*console"; -- Log to the console, useful for debugging with daemonize=false -- "*console"; -- Log to the console, useful for debugging with daemonize=false
} }
------ Components ------ ------ Components ------
-- You can specify components to add hosts that provide special services, -- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports. -- like multi-user conferences, and transports.
---Set up a local BOSH service ---Set up a local BOSH service
Component "localhost" "http" Component "localhost" "http"
modules_enabled = { "bosh" } modules_enabled = { "bosh" }
---Set up a MUC (multi-user chat) room server ---Set up a MUC (multi-user chat) room server
Component "muc.{{ main_domain }}" "muc" Component "muc.{{ main_domain }}" "muc"
name = "{{ main_domain }} Chatrooms" name = "{{ main_domain }} Chatrooms"
modules_enabled = { modules_enabled = {
"muc_limits"; "muc_limits";
"muc_log"; "muc_log";
"muc_log_http"; "muc_log_mam";
"muc_log_http";
"muc_vcard";
} }
muc_event_rate = 0.5 muc_event_rate = 0.5
muc_burst_factor = 10 muc_burst_factor = 10
muc_log_http_config = {
url_base = "logs";
theme = "metronome";
}
---Set up a PubSub server ---Set up a PubSub server
Component "pubsub.{{ main_domain }}" "pubsub" Component "pubsub.{{ main_domain }}" "pubsub"
name = "{{ main_domain }} Publish/Subscribe" name = "{{ main_domain }} Publish/Subscribe"
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a HTTP Upload service
Component "upload.{{ main_domain }}" "http_upload"
name = "{{ main_domain }} Sharing Service"
http_file_size_limit = 6*1024*1024
http_file_quota = 60*1024*1024
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a VJUD service ---Set up a VJUD service
Component "vjud.{{ main_domain }}" "vjud" Component "vjud.{{ main_domain }}" "vjud"
ud_disco_name = "{{ main_domain }} User Directory" ud_disco_name = "{{ main_domain }} User Directory"
----------- Virtual hosts ----------- ----------- Virtual hosts -----------
@ -190,4 +158,3 @@ Component "vjud.{{ main_domain }}" "vjud"
-- Settings under each VirtualHost entry apply *only* to that host. -- Settings under each VirtualHost entry apply *only* to that host.
Include "conf.d/*.cfg.lua" Include "conf.d/*.cfg.lua"

View file

@ -73,6 +73,6 @@ server {
access_by_lua_file /usr/share/ssowat/access.lua; access_by_lua_file /usr/share/ssowat/access.lua;
} }
include conf.d/yunohost_admin.conf.inc; include /etc/nginx/conf.d/yunohost_admin.conf.inc;
include conf.d/yunohost_api.conf.inc; include /etc/nginx/conf.d/yunohost_api.conf.inc;
} }

View file

@ -4,6 +4,7 @@ location /yunohost/api/ {
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
# Custom 502 error page # Custom 502 error page
error_page 502 /yunohost/api/error/502; error_page 502 /yunohost/api/error/502;

View file

@ -5,7 +5,7 @@ server {
access_by_lua_file /usr/share/ssowat/access.lua; access_by_lua_file /usr/share/ssowat/access.lua;
include conf.d/{{ domain }}.d/*.conf; include /etc/nginx/conf.d/{{ domain }}.d/*.conf;
location /yunohost/admin { location /yunohost/admin {
return 301 https://$http_host$request_uri; return 301 https://$http_host$request_uri;
@ -68,12 +68,21 @@ server {
add_header X-Permitted-Cross-Domain-Policies none; add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options "SAMEORIGIN"; add_header X-Frame-Options "SAMEORIGIN";
{% if domain_cert_ca == "Let's Encrypt" %}
# OCSP settings
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/yunohost/certs/{{ domain }}/crt.pem;
resolver 127.0.0.1 127.0.1.1 valid=300s;
resolver_timeout 5s;
{% endif %}
access_by_lua_file /usr/share/ssowat/access.lua; access_by_lua_file /usr/share/ssowat/access.lua;
include conf.d/{{ domain }}.d/*.conf; include /etc/nginx/conf.d/{{ domain }}.d/*.conf;
include conf.d/yunohost_admin.conf.inc; include /etc/nginx/conf.d/yunohost_admin.conf.inc;
include conf.d/yunohost_api.conf.inc; include /etc/nginx/conf.d/yunohost_api.conf.inc;
access_log /var/log/nginx/{{ domain }}-access.log; access_log /var/log/nginx/{{ domain }}-access.log;
error_log /var/log/nginx/{{ domain }}-error.log; error_log /var/log/nginx/{{ domain }}-error.log;

View file

@ -5,8 +5,8 @@
# See ldap.conf(5) for details # See ldap.conf(5) for details
# This file should be world readable but not world writable. # This file should be world readable but not world writable.
#BASE dc=example,dc=com BASE dc=yunohost,dc=org
#URI ldap://ldap.example.com ldap://ldap-master.example.com:666 URI ldap://localhost:389
#SIZELIMIT 12 #SIZELIMIT 12
#TIMELIMIT 15 #TIMELIMIT 15

View file

@ -43,7 +43,7 @@ unique_subject = no # Set to 'no' to allow creation of
new_certs_dir = $dir/newcerts # default place for new certs. new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/ca/cacert.pem # The CA certificate certificate = $dir/ca/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number #serial = $dir/serial # The current serial number
#crlnumber = $dir/crlnumber # the current crl number #crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL # must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL crl = $dir/crl.pem # The current CRL

21
debian/changelog vendored
View file

@ -1,3 +1,24 @@
yunohost (3.2.2) stable; urgency=low
* [hotfix] mod_auth_ldap: reflect SASL API changes in latest Metronome (#546)
* [enh] Add the internal helper ynh_handle_getopts_args (#520)
Thanks to all contributors (Maranda, Maniack) ! <3
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 28 Sep 2018 23:04:00 +0000
yunohost (3.2.1) stable; urgency=low
* Don't send an email if no certificate needs to be renewed (#540)
* Fix an issue with home backups (#541)
* Fix an issue with installs on OVH VPS
* Tell the user about post-install available in browser in bootprompt (#544)
* Improve Arabic translation
Thanks to all contributors (BoF, ljf, Aleks) ! <3
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 17 Sep 2018 18:06:00 +0000
yunohost (3.2.0) stable; urgency=low yunohost (3.2.0) stable; urgency=low
* Add many print and exec helpers (#523) * Add many print and exec helpers (#523)

View file

@ -56,8 +56,9 @@ function new_default_provider(host)
return nil, "Account creation/modification not available with LDAP."; return nil, "Account creation/modification not available with LDAP.";
end end
function provider.get_sasl_handler() function provider.get_sasl_handler(session)
local testpass_authentication_profile = { local testpass_authentication_profile = {
session = session,
plain_test = function(sasl, username, password, realm) plain_test = function(sasl, username, password, realm)
return provider.test_password(username, password), true; return provider.test_password(username, password), true;
end, end,

View file

@ -255,6 +255,7 @@
"mail_domain_unknown": "Unknown mail address domain '{domain:s}'", "mail_domain_unknown": "Unknown mail address domain '{domain:s}'",
"mail_forward_remove_failed": "Unable to remove mail forward '{mail:s}'", "mail_forward_remove_failed": "Unable to remove mail forward '{mail:s}'",
"mailbox_used_space_dovecot_down": "Dovecot mailbox service need to be up, if you want to get mailbox used space", "mailbox_used_space_dovecot_down": "Dovecot mailbox service need to be up, if you want to get mailbox used space",
"mail_unavailable": "This email address is reserved and shall be automatically allocated to the very first user",
"maindomain_change_failed": "Unable to change the main domain", "maindomain_change_failed": "Unable to change the main domain",
"maindomain_changed": "The main domain has been changed", "maindomain_changed": "The main domain has been changed",
"migrate_tsig_end": "Migration to hmac-sha512 finished", "migrate_tsig_end": "Migration to hmac-sha512 finished",

View file

@ -346,7 +346,8 @@ def app_info(app, show_status=False, raw=False):
ret['settings'] = _get_app_settings(app) ret['settings'] = _get_app_settings(app)
# Determine upgradability # Determine upgradability
local_update_time = ret['settings'].get('update_time', ret['settings']['install_time']) # In case there is neither update_time nor install_time, we assume the app can/has to be upgraded
local_update_time = ret['settings'].get('update_time', ret['settings'].get('install_time', 0))
if 'lastUpdate' not in ret or 'git' not in ret: if 'lastUpdate' not in ret or 'git' not in ret:
upgradable = "url_required" upgradable = "url_required"

View file

@ -2187,7 +2187,7 @@ def backup_list(with_info=False, human_readable=False):
except ValueError: except ValueError:
continue continue
result.append(name) result.append(name)
result.sort() result.sort(key=lambda x: os.path.getctime(os.path.join(ARCHIVES_PATH, x+".tar.gz")))
if result and with_info: if result and with_info:
d = OrderedDict() d = OrderedDict()

View file

@ -209,6 +209,11 @@ def domain_dns_conf(domain, ttl=None):
for record in dns_conf["mail"]: for record in dns_conf["mail"]:
result += "\n{name} {ttl} IN {type} {value}".format(**record) result += "\n{name} {ttl} IN {type} {value}".format(**record)
result += "\n\n"
result += "; Extra"
for record in dns_conf["extra"]:
result += "\n{name} {ttl} IN {type} {value}".format(**record)
is_cli = True if msettings.get('interface') == 'cli' else False is_cli = True if msettings.get('interface') == 'cli' else False
if is_cli: if is_cli:
logger.info(m18n.n("domain_dns_conf_is_just_a_recommendation")) logger.info(m18n.n("domain_dns_conf_is_just_a_recommendation"))
@ -334,6 +339,9 @@ def _build_dns_conf(domain, ttl=3600):
{"type": "TXT", "name": "mail._domainkey", "value": "\"v=DKIM1; k=rsa; p=some-super-long-key\"", "ttl": 3600}, {"type": "TXT", "name": "mail._domainkey", "value": "\"v=DKIM1; k=rsa; p=some-super-long-key\"", "ttl": 3600},
{"type": "TXT", "name": "_dmarc", "value": "\"v=DMARC1; p=none\"", "ttl": 3600} {"type": "TXT", "name": "_dmarc", "value": "\"v=DMARC1; p=none\"", "ttl": 3600}
], ],
"extra": [
{"type": "CAA", "name": "@", "value": "128 issue 'letsencrypt.org", "ttl": 3600},
],
} }
""" """
@ -387,10 +395,16 @@ def _build_dns_conf(domain, ttl=3600):
["_dmarc", ttl, "TXT", '"v=DMARC1; p=none"'], ["_dmarc", ttl, "TXT", '"v=DMARC1; p=none"'],
] ]
# Extra
extra = [
["@", ttl, "CAA", "128 issue 'letsencrypt.org'"]
]
return { return {
"basic": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in basic], "basic": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in basic],
"xmpp": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in xmpp], "xmpp": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in xmpp],
"mail": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in mail], "mail": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in mail],
"extra": [{"name": name, "ttl": ttl, "type": type_, "value": value} for name, ttl, type_, value in extra],
} }

View file

@ -37,6 +37,8 @@ from moulinette.core import MoulinetteError
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import read_file, write_to_file, rm from moulinette.utils.filesystem import read_file, write_to_file, rm
from moulinette.utils.network import download_json from moulinette.utils.network import download_json
from moulinette.utils.process import check_output
from yunohost.domain import _get_maindomain, _build_dns_conf from yunohost.domain import _get_maindomain, _build_dns_conf
from yunohost.utils.network import get_public_ip from yunohost.utils.network import get_public_ip
@ -44,8 +46,6 @@ from yunohost.log import is_unit_operation
logger = getActionLogger('yunohost.dyndns') logger = getActionLogger('yunohost.dyndns')
OLD_IPV4_FILE = '/etc/yunohost/dyndns/old_ip'
OLD_IPV6_FILE = '/etc/yunohost/dyndns/old_ipv6'
DYNDNS_ZONE = '/etc/yunohost/dyndns/zone' DYNDNS_ZONE = '/etc/yunohost/dyndns/zone'
RE_DYNDNS_PRIVATE_KEY_MD5 = re.compile( RE_DYNDNS_PRIVATE_KEY_MD5 = re.compile(
@ -96,7 +96,7 @@ def _dyndns_available(provider, domain):
domain -- The full domain that you'd like.. e.g. "foo.nohost.me" domain -- The full domain that you'd like.. e.g. "foo.nohost.me"
Returns: Returns:
True if the domain is avaible, False otherwise. True if the domain is available, False otherwise.
""" """
logger.debug("Checking if domain %s is available on %s ..." logger.debug("Checking if domain %s is available on %s ..."
% (domain, provider)) % (domain, provider))
@ -193,32 +193,6 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
old_ipv4, old_ipv6 = (None, None) # (default values) old_ipv4, old_ipv6 = (None, None) # (default values)
if os.path.isfile(OLD_IPV4_FILE):
old_ipv4 = read_file(OLD_IPV4_FILE).rstrip()
if os.path.isfile(OLD_IPV6_FILE):
old_ipv6 = read_file(OLD_IPV6_FILE).rstrip()
# Get current IPv4 and IPv6
ipv4_ = get_public_ip()
ipv6_ = get_public_ip(6)
if ipv4 is None:
ipv4 = ipv4_
if ipv6 is None:
ipv6 = ipv6_
logger.debug("Old IPv4/v6 are (%s, %s)" % (old_ipv4, old_ipv6))
logger.debug("Requested IPv4/v6 are (%s, %s)" % (ipv4, ipv6))
# no need to update
if old_ipv4 == ipv4 and old_ipv6 == ipv6:
logger.info("No updated needed.")
return
else:
logger.info("Updated needed, going on...")
# If domain is not given, try to guess it from keys available... # If domain is not given, try to guess it from keys available...
if domain is None: if domain is None:
(domain, key) = _guess_current_dyndns_domain(dyn_host) (domain, key) = _guess_current_dyndns_domain(dyn_host)
@ -262,7 +236,32 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
'zone %s' % host, 'zone %s' % host,
] ]
old_ipv4 = check_output("dig @%s +short %s" % (dyn_host, domain)).strip() or None
old_ipv6 = check_output("dig @%s +short aaaa %s" % (dyn_host, domain)).strip() or None
# Get current IPv4 and IPv6
ipv4_ = get_public_ip()
ipv6_ = get_public_ip(6)
if ipv4 is None:
ipv4 = ipv4_
if ipv6 is None:
ipv6 = ipv6_
logger.debug("Old IPv4/v6 are (%s, %s)" % (old_ipv4, old_ipv6))
logger.debug("Requested IPv4/v6 are (%s, %s)" % (ipv4, ipv6))
# no need to update
if old_ipv4 == ipv4 and old_ipv6 == ipv6:
logger.info("No updated needed.")
return
else:
logger.info("Updated needed, going on...")
dns_conf = _build_dns_conf(domain) dns_conf = _build_dns_conf(domain)
del dns_conf["extra"] # Ignore records from the 'extra' category
# Delete the old records for all domain/subdomains # Delete the old records for all domain/subdomains
@ -304,18 +303,11 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
command = ["/usr/bin/nsupdate", "-k", key, DYNDNS_ZONE] command = ["/usr/bin/nsupdate", "-k", key, DYNDNS_ZONE]
subprocess.check_call(command) subprocess.check_call(command)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
rm(OLD_IPV4_FILE, force=True) # Remove file (ignore if non-existent)
rm(OLD_IPV6_FILE, force=True) # Remove file (ignore if non-existent)
raise MoulinetteError(errno.EPERM, raise MoulinetteError(errno.EPERM,
m18n.n('dyndns_ip_update_failed')) m18n.n('dyndns_ip_update_failed'))
logger.success(m18n.n('dyndns_ip_updated')) logger.success(m18n.n('dyndns_ip_updated'))
if ipv4 is not None:
write_to_file(OLD_IPV4_FILE, ipv4)
if ipv6 is not None:
write_to_file(OLD_IPV6_FILE, ipv6)
def dyndns_installcron(): def dyndns_installcron():
""" """

View file

@ -358,7 +358,6 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False):
service_regen_conf(['ssl'], force=True) service_regen_conf(['ssl'], force=True)
ssl_dir = '/usr/share/yunohost/yunohost-config/ssl/yunoCA' ssl_dir = '/usr/share/yunohost/yunohost-config/ssl/yunoCA'
commands = [ commands = [
'echo "01" > %s/serial' % ssl_dir,
'rm %s/index.txt' % ssl_dir, 'rm %s/index.txt' % ssl_dir,
'touch %s/index.txt' % ssl_dir, 'touch %s/index.txt' % ssl_dir,
'cp %s/openssl.cnf %s/openssl.ca.cnf' % (ssl_dir, ssl_dir), 'cp %s/openssl.cnf %s/openssl.ca.cnf' % (ssl_dir, ssl_dir),

View file

@ -127,6 +127,17 @@ def user_create(operation_logger, auth, username, firstname, lastname, mail, pas
all_existing_usernames = {x.pw_name for x in pwd.getpwall()} all_existing_usernames = {x.pw_name for x in pwd.getpwall()}
if username in all_existing_usernames: if username in all_existing_usernames:
raise MoulinetteError(errno.EEXIST, m18n.n('system_username_exists')) raise MoulinetteError(errno.EEXIST, m18n.n('system_username_exists'))
main_domain = _get_maindomain()
aliases = [
'root@' + main_domain,
'admin@' + main_domain,
'webmaster@' + main_domain,
'postmaster@' + main_domain,
]
if mail in aliases:
raise MoulinetteError(errno.EEXIST,m18n.n('mail_unavailable'))
# Check that the mail domain exists # Check that the mail domain exists
if mail.split("@")[1] not in domain_list(auth)['domains']: if mail.split("@")[1] not in domain_list(auth)['domains']:
@ -166,13 +177,6 @@ def user_create(operation_logger, auth, username, firstname, lastname, mail, pas
# If it is the first user, add some aliases # If it is the first user, add some aliases
if not auth.search(base='ou=users,dc=yunohost,dc=org', filter='uid=*'): if not auth.search(base='ou=users,dc=yunohost,dc=org', filter='uid=*'):
main_domain = _get_maindomain()
aliases = [
'root@' + main_domain,
'admin@' + main_domain,
'webmaster@' + main_domain,
'postmaster@' + main_domain,
]
attr_dict['mail'] = [attr_dict['mail']] + aliases attr_dict['mail'] = [attr_dict['mail']] + aliases
# If exists, remove the redirection from the SSO # If exists, remove the redirection from the SSO
@ -306,11 +310,21 @@ def user_update(operation_logger, auth, username, firstname=None, lastname=None,
new_attr_dict['userPassword'] = _hash_user_password(change_password) new_attr_dict['userPassword'] = _hash_user_password(change_password)
if mail: if mail:
main_domain = _get_maindomain()
aliases = [
'root@' + main_domain,
'admin@' + main_domain,
'webmaster@' + main_domain,
'postmaster@' + main_domain,
]
auth.validate_uniqueness({'mail': mail}) auth.validate_uniqueness({'mail': mail})
if mail[mail.find('@') + 1:] not in domains: if mail[mail.find('@') + 1:] not in domains:
raise MoulinetteError(errno.EINVAL, raise MoulinetteError(errno.EINVAL,
m18n.n('mail_domain_unknown', m18n.n('mail_domain_unknown',
domain=mail[mail.find('@') + 1:])) domain=mail[mail.find('@') + 1:]))
if mail in aliases:
raise MoulinetteError(errno.EEXIST,m18n.n('mail_unavailable'))
del user['mail'][0] del user['mail'][0]
new_attr_dict['mail'] = [mail] + user['mail'] new_attr_dict['mail'] = [mail] + user['mail']