From patchwork Thu Nov 22 23:36:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Mendoza-Jonas X-Patchwork-Id: 1002065 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 431G8Y3vCsz9s0n for ; Fri, 23 Nov 2018 10:38:05 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="cWHQPXOL"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="aDq50aEj"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 431G8Y286VzDqSD for ; Fri, 23 Nov 2018 10:38:05 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="cWHQPXOL"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="aDq50aEj"; dkim-atps=neutral X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=mendozajonas.com (client-ip=66.111.4.28; helo=out4-smtp.messagingengine.com; envelope-from=sam@mendozajonas.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="cWHQPXOL"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="aDq50aEj"; dkim-atps=neutral Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 431G7D1GPBzDqS1 for ; Fri, 23 Nov 2018 10:36:56 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id D2CEA20DC2; Thu, 22 Nov 2018 18:36:50 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Thu, 22 Nov 2018 18:36:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= mendozajonas.com; h=from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; s=fm1; bh=xvscBvzmAFsRu3t32i2wLu/n2XWOVuSPsHYs7SMkhkE=; b=cWHQP XOLdATmtaKZRxHVCO6bY/DmAC2eaw+ytGkl7oBROCz+SUu5dqaiI3qD4OA9WTF9O k7mbrYmiBPAyXnlqGrF1fE4qh0SbYEBn2BbwerTV9cwMdHDMT644LH4tyw4pc4F4 9Kzg3VtzQhCETSGyDGVGfruiAcUbaXKxkEkqM0UeIDonLeUrvCZfDAN+NzSolE3E shs3/92AkyEpkcY+DKt9Gcp76OvIfFLJWJyQAx0rfugzWdNevFb+HJzv3R5HGFOO m26roT2iziBYwdHrCLkbR5Z07Bv48ow23MSBaExRAF7Fc4lOXBRTOuz7XWldSLn8 TSXwDdZbW0/rsrvCQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=xvscBvzmAFsRu3t32i2wLu/n2XWOVuSPsHYs7SMkhkE=; b=aDq50aEj wsPft/qUISdSXvRJoK99xLoYPQBwujW2RT8gWdcL6ltr3HkYIxlkU4sOaNVamEe9 TXYnVzWaS7+j4/0jTvF9l53EjtKaMwP34tV+tMx6YN9phZ2kKkpMjddprG22bVrI xybfp32IAHH9dY6EPiHVGazpfUbpa+p8S7JIXX+DpAoMZHs1yBbD2mqCjeApLYMS 9kC18A3r7/QlERNJ3Of4NOBk55UmkrkV3MHOvpP64iyRulyj/qTH4VAFaUsb46xA g8bK7IBDVVcMoPXDdKWmgNjSpRB4KZNo8y3IaahTWXyBTzOyZiKxxPzz30i3VOWg 4HkciW90m/Cq8Q== X-ME-Sender: X-ME-Proxy: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id 27B90102E0; Thu, 22 Nov 2018 18:36:48 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH 05/13] lib/crypt: Add helpers for operating on /etc/shadow Date: Fri, 23 Nov 2018 10:36:22 +1100 Message-Id: <20181122233630.6303-6-sam@mendozajonas.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181122233630.6303-1-sam@mendozajonas.com> References: <20181122233630.6303-1-sam@mendozajonas.com> MIME-Version: 1.0 X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Mendoza-Jonas Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" Provides helper functions for reading, writing, and checking against /etc/shadow. The main use case if for authenticating clients against the "system" password, which is set as the root password. Signed-off-by: Samuel Mendoza-Jonas --- configure.ac | 22 ++++++++ lib/Makefile.am | 9 ++++ lib/crypt/crypt.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++ lib/crypt/crypt.h | 49 ++++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 lib/crypt/crypt.c create mode 100644 lib/crypt/crypt.h diff --git a/configure.ac b/configure.ac index 2bf6e6f6..4151b002 100644 --- a/configure.ac +++ b/configure.ac @@ -76,6 +76,27 @@ AC_CHECK_LIB([devmapper], [dm_task_create], [AC_MSG_FAILURE([The libdevmapper development library is required by petitboot. Try installing the package libdevmapper-dev or device-mapper-devel.])] ) +AC_ARG_ENABLE( + [crypt], + [AS_HELP_STRING( + [--enable-crypt], + [Include crypt support to enable password use [default=no]] + )], + [], + [enable_crypt=no] +) +AM_CONDITIONAL([ENABLE_CRYPT], [test "x$enable_crypt" = "xyes"]) +AS_IF([test "x$enable_crypt" = "xyes"], + [AC_DEFINE(CRYPT_SUPPORT, 1, [Enable crypt/password support])], + [] +) +AS_IF([test "x$enable_crypt" = "xyes"], + AC_CHECK_LIB([crypt], [crypt], + [CRYPT_LIBS=-lcrypt], + [AC_MSG_FAILURE([shadow/crypt libs required])] + ) +) + AC_ARG_WITH([fdt], AS_HELP_STRING([--without-fdt], [Build without libfdt (default: no)])) @@ -455,6 +476,7 @@ AS_IF( AC_SUBST([UDEV_LIBS]) AC_SUBST([DEVMAPPER_LIBS]) +AC_SUBST([CRYPT_LIBS]) AC_SUBST([FDT_LIBS]) AC_SUBST([LIBFLASH_LIBS]) AC_SUBST([LIBTOOL_DEPS]) diff --git a/lib/Makefile.am b/lib/Makefile.am index 016a14dd..69a66c37 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -35,6 +35,7 @@ lib_libpbcore_la_CFLAGS = \ lib_libpbcore_la_SOURCES = \ lib/ccan/endian/endian.h \ + lib/crypt/crypt.h \ lib/file/file.h \ lib/file/file.c \ lib/fold/fold.h \ @@ -93,3 +94,11 @@ lib_libpbcore_la_SOURCES += \ lib/security/none.c endif endif + +if ENABLE_CRYPT +lib_libpbcore_la_SOURCES += \ + lib/crypt/crypt.c + +lib_libpbcore_la_LDFLAGS += \ + $(CRYPT_LIBS) +endif diff --git a/lib/crypt/crypt.c b/lib/crypt/crypt.c new file mode 100644 index 00000000..dcaf3afe --- /dev/null +++ b/lib/crypt/crypt.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2018 IBM Corporation + * + * 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; version 2 of the License. + * + * 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. + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "crypt.h" + +int crypt_set_password_hash(void *ctx, const char *hash) +{ + struct spwd *shadow; + FILE *fp; + int rc; + + shadow = getspnam("root"); + if (!shadow) { + pb_log("Could not find root shadow\n"); + return -1; + } + + shadow->sp_pwdp = talloc_strdup(ctx, hash); + if (!shadow->sp_pwdp) { + pb_log("Could not assign password\n"); + return -1; + } + + lckpwdf(); + + fp = fopen("/etc/shadow", "w+"); + if (!fp) { + pb_log("Could not open shadow file\n"); + rc = -1; + goto out; + } + + rc = putspent(shadow, fp); + if (rc) + pb_log("Failed to set password hash\n"); + + talloc_free(shadow->sp_pwdp); +out: + fclose(fp); + ulckpwdf(); + return rc; +} + +static const char *crypt_hash_password(const char *password) +{ + struct spwd *shadow; + char *hash; + + shadow = getspnam("root"); + if (!shadow) { + pb_log("Could not find root shadow\n"); + return NULL; + } + + hash = crypt(password ?: "", shadow->sp_pwdp); + if (!hash) + pb_log("Could not create hash, %m\n"); + + + return hash; +} + + +int crypt_set_password(void *ctx, const char *password) +{ + const char *hash; + + hash = crypt_hash_password(password); + if (!hash) + return -1; + + return crypt_set_password_hash(ctx, hash); +} + +char *crypt_get_hash(void *ctx) +{ + struct spwd *shadow; + + shadow = getspnam("root"); + if (!shadow) { + pb_log("Could not find root shadow\n"); + return false; + } + + return talloc_strdup(ctx, shadow->sp_pwdp); +} + +bool crypt_check_password(const char *password) +{ + struct spwd *shadow; + char *hash; + + shadow = getspnam("root"); + if (!shadow) { + pb_log("Could not find root shadow\n"); + return false; + } + + hash = crypt(password ? : "", shadow->sp_pwdp); + if (!hash) { + pb_log("Could not create hash, %m\n"); + return false; + } + + return strncmp(shadow->sp_pwdp, hash, strlen(shadow->sp_pwdp)) == 0; +} diff --git a/lib/crypt/crypt.h b/lib/crypt/crypt.h new file mode 100644 index 00000000..4b242f0c --- /dev/null +++ b/lib/crypt/crypt.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2018 IBM Corporation + * + * 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; version 2 of the License. + * + * 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. + * + */ +#ifndef CRYPT_H +#define CRYPT_H + +#include "config.h" + +#ifdef CRYPT_SUPPORT + +char *crypt_get_hash(void *ctx); +bool crypt_check_password(const char *password); +int crypt_set_password(void *ctx, const char *password); +int crypt_set_password_hash(void *ctx, const char *hash); + +#else + +static inline char *crypt_get_hash(void *ctx __attribute__((unused))) +{ + return NULL; +} +static inline bool crypt_check_password( + const char *password __attribute__((unused))) +{ + return false; +} +static inline int crypt_set_password(void *ctx __attribute__((unused)), + const char *password __attribute__((unused))) +{ + return -1; +} +static inline int crypt_set_password_hash(void *ctx __attribute__((unused)), + const char *hash __attribute__((unused))) +{ + return -1; +} + +#endif +#endif /* CRYPT_H */