Merge pull request #4 from Microsoft/remove-agent

Removed password agent
This commit is contained in:
Mike Brasher 2017-08-30 15:35:11 -05:00 коммит произвёл GitHub
Родитель 835f8cd848 f1f35ed914
Коммит 6dc29b4aaa
16 изменённых файлов: 48 добавлений и 777 удалений

Просмотреть файл

@ -23,7 +23,7 @@ define NL
endef
DIRS = striplic 3rdparty posix lsvmutils lsvmtool lsvmload policy password-agent
DIRS = striplic 3rdparty posix lsvmutils lsvmtool lsvmload policy
all:
$(foreach i, $(DIRS), $(MAKE) -C $(i) $(NL) )

Просмотреть файл

@ -251,6 +251,16 @@ rm -f ${lsvmprepfile}
${top}/scripts/encryptboot
chkerr "$?" "$0: failed to encrypt the boot drive"
##==============================================================================
##
## Set up the root drive:
##
##==============================================================================
if [[ ${vendor} != "ubuntu" ]]; then
${top}/scripts/setuproot
chkerr "$?" "$0: failed to setup root drive"
fi
##==============================================================================
##
## install_lsvmtool(lsvmtool)

Просмотреть файл

@ -1,39 +0,0 @@
include ../defs.mak
TARGET=$(BINDIR)/lsvmtool-password-agent
SOURCES=lsvmtool-password-agent.c
INCLUDES=-I$(TOP)
LIBRARIES=-L$(LIBDIR) -llsvmutils -pthread
SHARED=-Wall -o $(TARGET) $(INCLUDES) $(SOURCES) $(LIBRARIES)
ifndef TIMEOUT
TIMEOUT=15000
endif
all: debug
release:
gcc -D TIMEOUT=$(TIMEOUT) $(SHARED)
debug:
gcc -D DEBUG -D TIMEOUT=$(TIMEOUT) $(SHARED)
debug-no-cap:
gcc -D DEBUG -D TIMEOUT=$(TIMEOUT) $(SHARED)
CLEAN = \
*.o \
$(TARGET) \
tmp \
KEY0 \
KEY1 \
KEY2
clean:
rm -rf $(CLEAN)
distclean: clean
tests:
./agent-tests

Просмотреть файл

@ -1,79 +0,0 @@
#!/bin/bash
run_agent()
{
../build/bin/lsvmtool-password-agent tmp/bootkey tmp/rootkey
}
ask_boot()
{
systemd-ask-password --no-tty "Please give password for /boot:"
}
ask_root()
{
systemd-ask-password --no-tty "Please give password for luks-123:"
}
setup()
{
rm -rf tmp
mkdir -p tmp
echo -n "BOOTKEY" > tmp/bootkey
echo -n "ROOTKEY" > tmp/rootkey
}
reset_test()
{
rm -f KEY0
rm -f KEY1
rm -f KEY2
}
# Test cases on order of what program gets called.
# r = root ask (waits until it finds the key and then decrypts root)
# a = agent (password agent)
# b = boot ask (unseals the keys and then decrypts boot)
setup
make debug-no-cap TIMEOUT=3000
first=(run_agent run_agent ask_boot ask_boot ask_root ask_root)
second=(ask_boot ask_root run_agent ask_root run_agent ask_boot)
third=(ask_root ask_boot ask_root run_agent ask_boot run_agent)
invalid=0
for i in "${!first[@]}"; do
reset_test
cmd1="${first[$i]}"
cmd2="${second[$i]}"
cmd3="${third[$i]}"
printf "Starting test $i: $cmd1 $cmd2 $cmd3\n"
$cmd1 > KEY0 &
$cmd2 > KEY1 &
$cmd3 > KEY2
cmds=("$cmd1" "$cmd2" "$cmd3")
# Wait for requests to finish
sleep 5
for j in "${!cmds[@]}"; do
chk_cmd="${cmds[$j]}"
key=$(<"KEY$j")
if [[ "$chk_cmd" == "ask_boot" && "$key" != "BOOTKEY" ]]; then
printf " ERROR: wrong bootkey $cmd1 $cmd2 $cmd3\n"
invalid=1
fi
if [[ "$chk_cmd" == "ask_root" && "$key" != "ROOTKEY" ]]; then
printf " ERROR: wrong rootkey $cmd1 $cmd2 $cmd3\n"
invalid=1
fi
done
done
echo "All tests complete!"
exit $invalid

Просмотреть файл

@ -1,445 +0,0 @@
/*
**==============================================================================
**
** LSVMTools
**
** MIT License
**
** Copyright (c) Microsoft Corporation. All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE
**
**==============================================================================
*/
#include <lsvmutils/buf.h>
#include <errno.h>
#include <dirent.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <inttypes.h>
#include <poll.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>
#ifdef DEBUG
#define PRINTLOG printf("%s(%d): %s(): %s\n", __FILE__, __LINE__, __FUNCTION__, strerror(errno));
#else
#define PRINTLOG
#endif
#define GOTO(LABEL) \
do \
{ \
PRINTLOG \
goto LABEL; \
} while (0)
static const char *WATCH_DIR = "/run/systemd/ask-password/";
static const char *PASS_PREFIX = "ask.";
static const char *INI_SECTION = "[Ask]\n";
static const char *INI_MESSAGE = "Message=";
static const char *INI_SOCKET = "Socket=";
static const char *BOOT_DRIVE_NAME = "boot";
static void dump_inotify_event(struct inotify_event *event)
{
#ifdef DEBUG
printf("wd: %d\n", event->wd);
printf("mask: %" PRIu32 "\n", event->mask);
printf("cookie: %" PRIu32 "\n", event->cookie);
printf("len: %" PRIu32 "\n", event->len);
printf("name: %s\n", event->name);
#endif
}
static char *retrieve_password(int is_boot, const char *bootkey, const char *rootkey)
{
char *password = NULL;
const char *keyname = NULL;
struct stat file_info;
int pass_fd = -1;
keyname = is_boot ? bootkey : rootkey;
if (stat(keyname, &file_info) != 0)
GOTO(err);
password = (char*) malloc(file_info.st_size + 1);
if (password == NULL)
GOTO(err);
pass_fd = open(keyname, O_RDONLY);
if (pass_fd == -1)
GOTO(err);
if (read(pass_fd, password, file_info.st_size) != file_info.st_size)
GOTO(err);
password[file_info.st_size] = '\0';
goto done;
err:
if (password)
free(password);
password = NULL;
done:
if (pass_fd != -1)
close(pass_fd);
return password;
}
static int send_password(const char *pass, const char *socket_name)
{
int sock_fd = -1;
char *packet = NULL;
ssize_t packet_length = 0;
struct sockaddr_un addr;
int err = -1;
/* Create the password response packet. */
packet_length = strlen(pass) + 2;
packet = malloc(packet_length);
if (packet == NULL)
GOTO(done);
packet[0] = '+';
printf("%s\n", pass);
memcpy(packet+1, pass, packet_length-1);
/* Send the packet. */
sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sock_fd == -1)
GOTO(done);
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path));
if (sendto(sock_fd, packet, packet_length, 0, (struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0)
GOTO(done);
err = 0;
done:
if (packet)
free(packet);
if (sock_fd != -1)
close(sock_fd);
return err;
}
static int search_for_ask(FILE *fp)
{
char *lineptr = NULL;
size_t n = 0;
int err = 0;
do
{
if (getline(&lineptr, &n, fp) == -1)
{
err = -1;
break;
}
} while (strcmp(lineptr, INI_SECTION) != 0);
free(lineptr);
return err;
}
static int parse_ask_section(FILE *fp, int *is_boot, char **socket_name)
{
char *lineptr = NULL;
size_t n = 0;
char *tmp_socket_name = NULL;
while (1)
{
ssize_t bytes_read;
if ((bytes_read = getline(&lineptr, &n, fp)) == -1)
break;
if (strncmp(lineptr, INI_MESSAGE, strlen(INI_MESSAGE)) == 0)
printf("ALERT: %s", lineptr);
if (strncmp(lineptr, INI_MESSAGE, strlen(INI_MESSAGE)) == 0
&& strstr(lineptr, BOOT_DRIVE_NAME) != NULL)
{
*is_boot = 1;
}
if (strncmp(lineptr, INI_SOCKET, strlen(INI_SOCKET)) == 0)
{
size_t off = strlen(INI_SOCKET);
size_t size = bytes_read - off;
/* Should have only 1 socket field. */
if (tmp_socket_name != NULL)
break;
tmp_socket_name = (char*) malloc(size);
if (!tmp_socket_name)
break;
memcpy(tmp_socket_name, lineptr + off, size);
/* Change ending \n to a NULL. */
tmp_socket_name[size-1] = '\0';
}
}
free(lineptr);
if (!feof(fp))
{
free(tmp_socket_name);
return -1;
}
*socket_name = tmp_socket_name;
return 0;
}
static int handle_and_send_pass(const char *socket_name, int is_boot, const char *bootkey, const char *rootkey)
{
char *pass = NULL;
int err = -1;
pass = retrieve_password(is_boot, bootkey, rootkey);
if (pass == NULL)
return err;
err = send_password(pass, socket_name);
free(pass);
return err;
}
static int process_password_request(struct inotify_event *event, const char *bootkey, const char *rootkey)
{
FILE *fp = NULL;
char *path = NULL;
int err = -1;
char *socket_name = NULL;
int is_boot = 0;
dump_inotify_event(event);
/* Ignore anything that isn't ask.XXXX */
if (strncmp(event->name, PASS_PREFIX, strlen(PASS_PREFIX)) != 0)
return 0;
/* Create the path to file and open it. */
path = (char*) malloc(strlen(WATCH_DIR) + event->len);
if (!path)
GOTO(done);
memcpy(path, WATCH_DIR, strlen(WATCH_DIR));
memcpy(path + strlen(WATCH_DIR), event->name, event->len);
fp = fopen(path, "r");
if (!fp)
GOTO(done);
/* Save Socket= Field. */
err = search_for_ask(fp);
if (err)
GOTO(done);
err = parse_ask_section(fp, &is_boot, &socket_name);
if (err || socket_name == NULL)
GOTO(done);
/* Finally, execute the unseal and send the password. */
err = handle_and_send_pass(socket_name, is_boot, bootkey, rootkey);
if (err)
GOTO(done);
done:
if (path)
free(path);
if (socket_name)
free(socket_name);
if (fp)
fclose(fp);
return err;
}
static int buf_contains_str(BufPtr *seen, const char *name, uint32_t namelen)
{
UINTN i = 0;
for (; i < seen->size; i++)
{
if (strncmp(name, (char*) seen->data[i], namelen) == 0)
return 1;
}
return 0;
}
static int read_password_request(int fd, BufPtr *seen, const char *bootkey, const char *rootkey)
{
uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1];
uint8_t *p = buf;
int bytes_read;
int err = -1;
bytes_read = read(fd, buf, sizeof(buf));
if (bytes_read == -1)
GOTO(done);
while (p < buf + bytes_read)
{
struct inotify_event *event = (struct inotify_event*) p;
char *tmp = NULL;
p += sizeof(struct inotify_event) + event->len;
/* Check in buffer & skip duplicates. */
if (buf_contains_str(seen, event->name, event->len))
continue;
tmp = (char*) malloc(event->len);
if (tmp == NULL)
GOTO(done);
memcpy(tmp, event->name, event->len);
if (BufPtrAppend(seen, (const void **) &tmp, 1))
{
free(tmp);
GOTO(done);
}
process_password_request(event, bootkey, rootkey);
}
err = 0;
done:
return err;
}
static int watch_password_requests(int fd, const char *bootkey, const char *rootkey)
{
/* Watch directory with timeout. */
int err;
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
BufPtr seen = BUF_PTR_INITIALIZER;
do
{
err = poll(&pfd, 1, TIMEOUT);
if (err > 0)
{
read_password_request(fd, &seen, bootkey, rootkey);
/*if (func_err)
{
err = func_err;
goto done;
}*/
}
} while (err > 0);
//done:
{
UINTN i;
for (i = 0; i < seen.size; i++)
free(seen.data[i]);
BufPtrRelease(&seen);
}
return err;
}
static int update_directory(const char *dir)
{
DIR *dir_fd = NULL;
struct dirent *file;
int err = -1;
dir_fd = opendir(dir);
if (dir_fd == NULL)
GOTO(done);
while ((file = readdir(dir_fd)))
{
int file_fd = -1;
char path[PATH_MAX];
// Only pay attention to ask. requests
if (strncmp(file->d_name, PASS_PREFIX, strlen(PASS_PREFIX)) != 0)
continue;
strncpy(path, dir, PATH_MAX - NAME_MAX);
strncat(path, file->d_name, NAME_MAX);
file_fd = open(path, O_RDWR);
if (file_fd == -1)
GOTO(done);
close(file_fd);
}
err = 0;
done:
if (dir_fd)
closedir(dir_fd);
return err;
}
int main(int argc, char **argv)
{
int fd = -1;
int err = -1;
if (argc != 3)
{
printf("Usage: %s bootkey-path rootkey-path.\n", argv[0]);
return -1;
}
fd = inotify_init();
if (fd == -1)
GOTO(done);
if (inotify_add_watch(fd, WATCH_DIR, IN_CLOSE_WRITE | IN_MOVED_TO) == -1)
GOTO(done);
/* Update all the files now that we are watching the directory */
err = update_directory(WATCH_DIR);
if (err)
GOTO(done);
err = watch_password_requests(fd, argv[1], argv[2]);
if (err)
GOTO(done);
done:
if (fd != -1)
close(fd);
return err;
}

Просмотреть файл

@ -22,48 +22,6 @@ if [ "$?" != "0" ]; then
exit 1
fi
##==============================================================================
##
## install lsvmtool-password-agent:
##
##==============================================================================
src=${top}/build/bin/lsvmtool-password-agent
dest=/sbin/lsvmtool-password-agent
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
systemd_path=/usr/lib/systemd/system
src=${top}/scripts/lsvmtool-password-agent.path
dest=${systemd_path}/lsvmtool-password-agent.path
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
mkdir -p ${systemd_path}/sysinit.target.wants
src=${dest}
dest=${systemd_path}/sysinit.target.wants/lsvmtool-password-agent.path
ln -sfr ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: ln failed: ${src} => ${dest}"
exit 1
fi
src=${top}/scripts/lsvmtool-password-agent.service
dest=${systemd_path}/lsvmtool-password-agent.service
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
##==============================================================================
##
## install module-setup.sh:

Просмотреть файл

@ -16,25 +16,6 @@ fi
dest=/sbin/lsvmtool
rm -rf ${dest}
##==============================================================================
##
## remove lsvmtool-password-agent:
##
##==============================================================================
dest=/sbin/lsvmtool-password-agent
rm -rf ${dest}
systemd_path=/usr/lib/systemd/system
dest=${systemd_path}/lsvmtool-password-agent.path
rm -rf ${dest}
dest=${systemd_path}/sysinit.target.wants/lsvmtool-password-agent.path
rm -rf ${dest}
dest=${systemd_path}/lsvmtool-password-agent.service
rm -rf ${dest}
##==============================================================================
##
## remove module-setup.sh:

Просмотреть файл

@ -42,7 +42,7 @@ patch_crypttab()
### Get the UUID of the dev-mapper device:
uuid=`blkid $luksdev | cut -d '"' -f 2`
old="^$devmapbase\>.*"
new="$devmapbase UUID=$uuid none luks,discard"
new="$devmapbase UUID=$uuid /etc/lsvmload/bootkey luks,discard"
### Test whether /etc/crypttab already has a boot entry:
grep -q -s "^$devmapbase\>" /etc/crypttab

Просмотреть файл

@ -1,13 +0,0 @@
[Unit]
Description=LSVMTOOL Password Agent
DefaultDependencies=no
Conflicts=shutdown.target
After=plymouth-start.service
Before=paths.target shutdown.target
[Path]
DirectoryNotEmpty=/run/systemd/ask-password
MakeDirectory=yes
[Install]
WantedBy=sysinit.target

Просмотреть файл

@ -1,11 +0,0 @@
[Unit]
Description=LSVMTOOL Password Agent
DefaultDependencies=no
Conflicts=shutdown.target
After=plymouth-start.service
Before=shutdown.target
[Service]
ExecStart=/sbin/lsvmtool-password-agent /etc/lsvmload/bootkey /etc/lsvmload/rootkey
StandardOutput=journal+console
StandardError=journal+console

Просмотреть файл

@ -25,11 +25,6 @@ check()
install()
{
inst "lsvmtool"
inst "lsvmtool-password-agent"
inst "$systemdsystemunitdir/lsvmtool-password-agent.path"
inst "$systemdsystemunitdir/lsvmtool-password-agent.service"
mkdir -p "${initdir}${systemdsystemconfdir}/sysinit.target.wants"
inst "$systemdsystemunitdir/sysinit.target.wants/lsvmtool-password-agent.path"
}
installkernel()

Просмотреть файл

@ -22,48 +22,6 @@ if [ "$?" != "0" ]; then
exit 1
fi
##==============================================================================
##
## install lsvmtool-password-agent:
##
##==============================================================================
src=${top}/build/bin/lsvmtool-password-agent
dest=/sbin/lsvmtool-password-agent
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
systemd_path=/usr/lib/systemd/system
src=${top}/scripts/lsvmtool-password-agent.path
dest=${systemd_path}/lsvmtool-password-agent.path
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
mkdir -p ${systemd_path}/sysinit.target.wants
src=${dest}
dest=${systemd_path}/sysinit.target.wants/lsvmtool-password-agent.path
ln -sfr ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: ln failed: ${src} => ${dest}"
exit 1
fi
src=${top}/scripts/lsvmtool-password-agent.service
dest=${systemd_path}/lsvmtool-password-agent.service
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
##==============================================================================
##
## install module-setup.sh:

Просмотреть файл

@ -16,25 +16,6 @@ fi
dest=/sbin/lsvmtool
rm -rf ${dest}
##==============================================================================
##
## remove lsvmtool-password-agent:
##
##==============================================================================
dest=/sbin/lsvmtool-password-agent
rm -rf ${dest}
systemd_path=/usr/lib/systemd/system
dest=${systemd_path}/lsvmtool-password-agent.path
rm -rf ${dest}
dest=${systemd_path}/sysinit.target.wants/lsvmtool-password-agent.path
rm -rf ${dest}
dest=${systemd_path}/lsvmtool-password-agent.service
rm -rf ${dest}
##==============================================================================
##
## remove module-setup.sh:

36
scripts/setuproot Executable file
Просмотреть файл

@ -0,0 +1,36 @@
#!/bin/bash
echo "Patching /etc/crypttab"
root=$($(dirname "$0")/rootdev)
if [[ -z "$root" ]]; then
echo "$0: no root device"
exit 1
fi
cryptroot=""
while read l; do
id=$(echo $l | cut -f2 -d " ")
path="$id"
# Either it's a path or a UUID prefix
if [[ "${path:0:1}" != "/" ]]; then
# UUID prefix. R
path=$(echo -n "$path" | sed 's/UUID=//g')
path=$(blkid -U "$path")
fi
path=$(readlink -f "$path")
if [[ "$path" == "$root" ]]; then
cryptroot="$id"
break
fi
done < /etc/crypttab
if [[ -z "$cryptroot" ]]; then
# did not find root device. Patch it to /etc/crypttab
printf "rootdev %s /etc/lsvmload/rootkey luks,discard", "$root" >> /etc/crypttab
exit 0
fi
awk -v targ="$cryptroot" '{ if ($2 == targ) { $3="/etc/lsvmload/rootkey" }; print }' /etc/crypttab > /etc/crypttab.new
mv /etc/crypttab.new /etc/crypttab
exit 0

Просмотреть файл

@ -22,48 +22,6 @@ if [ "$?" != "0" ]; then
exit 1
fi
##==============================================================================
##
## install lsvmtool-password-agent:
##
##==============================================================================
src=${top}/build/bin/lsvmtool-password-agent
dest=/sbin/lsvmtool-password-agent
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
systemd_path=/usr/lib/systemd/system
src=${top}/scripts/lsvmtool-password-agent.path
dest=${systemd_path}/lsvmtool-password-agent.path
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
mkdir -p ${systemd_path}/sysinit.target.wants
src=${dest}
dest=${systemd_path}/sysinit.target.wants/lsvmtool-password-agent.path
ln -sfr ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: ln failed: ${src} => ${dest}"
exit 1
fi
src=${top}/scripts/lsvmtool-password-agent.service
dest=${systemd_path}/lsvmtool-password-agent.service
install -D ${src} ${dest}
if [ "$?" != "0" ]; then
echo "$0: install failed: ${src} => ${dest}"
exit 1
fi
##==============================================================================
##
## install module-setup.sh:

Просмотреть файл

@ -16,25 +16,6 @@ fi
dest=/sbin/lsvmtool
rm -rf ${dest}
##==============================================================================
##
## remove lsvmtool-password-agent:
##
##==============================================================================
dest=/sbin/lsvmtool-password-agent
rm -rf ${dest}
systemd_path=/usr/lib/systemd/system
dest=${systemd_path}/lsvmtool-password-agent.path
rm -rf ${dest}
dest=${systemd_path}/sysinit.target.wants/lsvmtool-password-agent.path
rm -rf ${dest}
dest=${systemd_path}/lsvmtool-password-agent.service
rm -rf ${dest}
##==============================================================================
##
## remove module-setup.sh: