Forked from samhocevar/gist:00eec26d9e9988d080ac
Last active
December 7, 2017 11:43
-
-
Save abakum/5be504bc7920a5f6dbd48e797c31715d to your computer and use it in GitHub Desktop.
Configure sshd on MSYS2 and run it as a Windows service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# | |
# msys2-sshd-setup.sh — configure sshd on MSYS2 and run it as a Windows service | |
# | |
# Please report issues and/or improvements to Sam Hocevar <[email protected]> | |
# | |
# Prerequisites: | |
# — MSYS2 itself: http://sourceforge.net/projects/msys2/ | |
# — admin tools: pacman -S openssh cygrunsrv mingw-w64-x86_64-editrights | |
# | |
# This script is a cleaned up and improved version of the procedure initially | |
# found at https://ghc.haskell.org/trac/ghc/wiki/Building/Windows/SSHD | |
# | |
# Changelog: | |
# 24 Aug 2015 — run server with -e to redirect logs to /var/log/sshd.log | |
# 06 Dec 2017 - add pacman, MSYSTEM_CARCH, MSYSTEM_PREFIX, mkpasswd -c, AcceptEnv MSYSTEM | |
# | |
# Installation | |
# | |
pacman -Sy | |
pacman -S --needed openssh | |
pacman -S --needed cygrunsrv | |
pacman -S --needed mingw-w64-${MSYSTEM_CARCH}-editrights | |
pacman -S --needed mingw-w64-${MSYSTEM_CARCH}-iconv | |
set -e | |
# | |
# Configuration | |
# | |
PRIV_USER=sshd_server | |
PRIV_NAME="Privileged user for sshd" | |
UNPRIV_USER=sshd # DO NOT CHANGE; this username is hardcoded in the openssh code | |
UNPRIV_NAME="Privilege separation user for sshd" | |
EMPTY_DIR=/var/empty | |
if [ "${LANG:0:3}" == "en_" ]; then | |
log="cat /var/log/sshd.log" | |
else | |
log="iconv -f $(cmd /c chcp|tr -dc [:digit:]) -t $(echo $LANG|sed -e 's/^[^.]*.//') /var/log/sshd.log" | |
fi | |
# | |
# Check installation sanity | |
# | |
if ! ${MSYSTEM_PREFIX}/bin/editrights -h >/dev/null; then | |
echo "ERROR: Missing 'editrights'. Try: pacman -S mingw-w64-${MSYSTEM_CARCH}-editrights." | |
exit 1 | |
fi | |
if ! cygrunsrv -v >/dev/null; then | |
echo "ERROR: Missing 'cygrunsrv'. Try: pacman -S cygrunsrv." | |
exit 1 | |
fi | |
if ! ssh-keygen -A; then | |
echo "ERROR: Missing 'ssh-keygen'. Try: pacman -S openssh." | |
exit 1 | |
fi | |
# | |
# The privileged cyg_server user | |
# | |
# Some random password; this is only needed internally by cygrunsrv and | |
# is limited to 14 characters by Windows (lol) | |
tmp_pass="$(tr -dc 'a-zA-Z0-9' < /dev/urandom | dd count=14 bs=1 2>/dev/null)" | |
echo "Add or update user ${PRIV_USER}"|tee /var/log/sshd.log | |
add="$(if ! net user "${PRIV_USER}" >/dev/null; then echo "//add"; fi)" | |
if ! net user "${PRIV_USER}" "${tmp_pass}" ${add} //fullname:"${PRIV_NAME}" \ | |
//homedir:"$(cygpath -w ${EMPTY_DIR})" //yes >>/var/log/sshd.log 2>&1; then | |
${log} | |
echo "ERROR: Unable to create Windows user ${PRIV_USER}"|tee -a /var/log/sshd.log | |
exit 1 | |
fi | |
echo "Add user ${PRIV_USER} to the Administrators group if necessary"|tee -a /var/log/sshd.log | |
admingroup="$(mkgroup -l | awk -F: '{if ($2 == "S-1-5-32-544") print $1;}')" | |
if ! (net localgroup "${admingroup}" | grep -q '^'"${PRIV_USER}"'$'); then | |
if ! net localgroup "${admingroup}" "${PRIV_USER}" //add >>/var/log/sshd.log 2>&1; then | |
${log} | |
echo "ERROR: Unable to add user ${PRIV_USER} to group ${admingroup}"|tee -a /var/log/sshd.log | |
exit 1 | |
fi | |
fi | |
# Infinite passwd expiry | |
passwd -e "${PRIV_USER}" | |
echo "Set required privileges fo user ${PRIV_USER}"|tee -a /var/log/sshd.log | |
for flag in SeAssignPrimaryTokenPrivilege SeCreateTokenPrivilege \ | |
SeTcbPrivilege SeDenyRemoteInteractiveLogonRight SeServiceLogonRight; do | |
if ! ${MSYSTEM_PREFIX}/bin/editrights -a "${flag}" -u "${PRIV_USER}"; then | |
echo "ERROR: Unable to give ${flag} rights to user ${PRIV_USER}"|tee -a /var/log/sshd.log | |
exit 1 | |
fi | |
done | |
net user "${PRIV_USER}" >>/var/log/sshd.log 2>&1 | |
# | |
# The unprivileged sshd user (for privilege separation) | |
# | |
echo "Add or update user ${UNPRIV_USER}"|tee -a /var/log/sshd.log | |
add="$(if ! net user "${UNPRIV_USER}" >/dev/null; then echo "//add"; fi)" | |
if ! net user "${UNPRIV_USER}" ${add} //fullname:"${UNPRIV_NAME}" \ | |
//homedir:"$(cygpath -w ${EMPTY_DIR})" //active:no >>/var/log/sshd.log 2>&1; then | |
${log} | |
echo "ERROR: Unable to create Windows user ${PRIV_USER}"|tee -a /var/log/sshd.log | |
exit 1 | |
fi | |
net user "${UNPRIV_USER}" >>/var/log/sshd.log 2>&1 | |
# | |
# Add or update /etc/passwd entries | |
# | |
#touch /etc/passwd | |
if [ ! /etc/passwd ]; then | |
# First run. Add current user to passwd | |
mkpasswd -c > /etc/passwd | |
# Avoid errors pertaining to the last login service | |
touch /var/log/lastlog | |
echo AcceptEnv MSYSTEM >> /etc/ssh/sshd_config | |
echo "To start shell as ${MSYSTEM} use:"|tee -a /var/log/sshd.log | |
echo "MSYSTEM=${MSYSTEM} ssh ..."|tee -a /var/log/sshd.log | |
fi | |
for u in "${PRIV_USER}" "${UNPRIV_USER}"; do | |
sed -i -e '/^'"${u}"':/d' /etc/passwd | |
SED='/^'"${u}"':/s?^\(\([^:]*:\)\{5\}\).*?\1'"${EMPTY_DIR}"':/bin/false?p' | |
mkpasswd -l -u "${u}" | sed -e 's/^[^:]*+//' | sed -ne "${SED}" \ | |
>> /etc/passwd | |
done | |
# | |
# Finally, register service with cygrunsrv and start it | |
# | |
cygrunsrv -R sshd || true | |
cygrunsrv -I sshd -d "MSYS2 sshd" -p \ | |
/usr/bin/sshd.exe -a "-D -e" -y tcpip -u "${PRIV_USER}" -w "${tmp_pass}" | |
echo "The SSH service should start automatically when Windows is rebooted. You can"|tee -a /var/log/sshd.log | |
echo "manually restart the service by running 'net stop sshd&net start sshd'"|tee -a /var/log/sshd.log | |
if ! net start sshd >>/var/log/sshd.log 2>&1; then | |
${log} | |
echo "ERROR: Unable to start sshd service"|tee -a /var/log/sshd.log | |
exit 1 | |
fi | |
${log} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment